Java tutorial
/******************************************************************************* * Copyright (c) 2010, 2011 LogSaw project and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * LogSaw project committers - initial API and implementation *******************************************************************************/ package net.sf.logsaw.ui.editors; import java.io.IOException; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import net.sf.logsaw.core.field.ALogEntryField; import net.sf.logsaw.core.field.ILogEntryFieldVisitor; import net.sf.logsaw.core.field.Level; import net.sf.logsaw.core.field.LogEntry; import net.sf.logsaw.core.field.model.DateLogEntryField; import net.sf.logsaw.core.field.model.LevelLogEntryField; import net.sf.logsaw.core.field.model.StringLogEntryField; import net.sf.logsaw.core.logresource.ILogResource; import net.sf.logsaw.core.query.IRestrictable; import net.sf.logsaw.index.IQueryContext; import net.sf.logsaw.index.IndexPlugin; import net.sf.logsaw.index.ResultPage; import net.sf.logsaw.ui.IHelpContexts; import net.sf.logsaw.ui.Messages; import net.sf.logsaw.ui.UIPlugin; import net.sf.logsaw.ui.viewers.LogEntryTableLabelProvider; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.dialogs.IPageChangedListener; import org.eclipse.jface.dialogs.PageChangedEvent; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.ColumnViewerEditor; import org.eclipse.jface.viewers.ColumnViewerEditorActivationEvent; import org.eclipse.jface.viewers.ColumnViewerEditorActivationStrategy; import org.eclipse.jface.viewers.FocusCellOwnerDrawHighlighter; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerEditor; import org.eclipse.jface.viewers.TableViewerFocusCellManager; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.EditorPart; import org.eclipse.ui.statushandlers.StatusManager; /** * @author Philipp Nanz */ public class LogViewEditor extends EditorPart implements ILogViewEditor { /** * The ID of the view as specified by the extension. */ public static final String ID = "net.sf.logsaw.ui.editors.LogViewEditor"; //$NON-NLS-1$ private TableViewer viewer; private TableViewerFocusCellManager focusCellManager; private LogEntryTableLabelProvider labelProvider; private Label resultLabel; private ResultPage currentPage; private LogViewEditorColumnConfiguration columnConfig; private List<IPageChangedListener> listeners = new ArrayList<IPageChangedListener>(); private int currentPageNumber; private int pageSize = 1000; private IEditorInput editorInput; private IQueryContext queryContext; /* (non-Javadoc) * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) */ @Override public void createPartControl(Composite parent) { Composite root = new Composite(parent, SWT.BORDER); GridLayout gridLayout = new GridLayout(); gridLayout.marginHeight = 0; gridLayout.marginWidth = 0; gridLayout.verticalSpacing = 0; root.setLayout(gridLayout); Composite top = new Composite(root, SWT.NONE); top.setLayout(new GridLayout()); top.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); resultLabel = new Label(top, SWT.NONE); resultLabel.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); Label label = new Label(root, SWT.SEPARATOR | SWT.HORIZONTAL); label.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false)); viewer = new TableViewer(root, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION); viewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); viewer.getTable().setHeaderVisible(true); viewer.getTable().setLinesVisible(true); labelProvider = new LogEntryTableLabelProvider(); labelProvider.setLog(getLogResource()); viewer.setLabelProvider(labelProvider); viewer.setContentProvider(new ArrayContentProvider()); getSite().setSelectionProvider(viewer); // Enable table cell navigation focusCellManager = new TableViewerFocusCellManager(viewer, new FocusCellOwnerDrawHighlighter(viewer)); ColumnViewerEditorActivationStrategy actSupport = new ColumnViewerEditorActivationStrategy(viewer) { @Override protected boolean isEditorActivationEvent(ColumnViewerEditorActivationEvent event) { return (event.eventType == ColumnViewerEditorActivationEvent.TRAVERSAL) || (event.eventType == ColumnViewerEditorActivationEvent.MOUSE_DOUBLE_CLICK_SELECTION) || ((event.eventType == ColumnViewerEditorActivationEvent.KEY_PRESSED) && (event.keyCode == SWT.CR)) || (event.eventType == ColumnViewerEditorActivationEvent.PROGRAMMATIC); } }; TableViewerEditor.create(viewer, focusCellManager, actSupport, ColumnViewerEditor.TABBING_HORIZONTAL | ColumnViewerEditor.TABBING_MOVE_TO_ROW_NEIGHBOR | ColumnViewerEditor.TABBING_VERTICAL | ColumnViewerEditor.KEYBOARD_ACTIVATION); // Setup popup menu hookContextMenu(); // Setup columns setColumnConfig(new LogViewEditorColumnConfiguration(getLogResource())); goToPage(1); // Enable dynamic help PlatformUI.getWorkbench().getHelpSystem().setHelp(viewer.getControl(), IHelpContexts.LOG_VIEWER); } private void hookContextMenu() { MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$ menuMgr.setRemoveAllWhenShown(true); menuMgr.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(IMenuManager manager) { // Other plug-ins can contribute their actions here manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); } }); Menu menu = menuMgr.createContextMenu(viewer.getControl()); viewer.getControl().setMenu(menu); getSite().registerContextMenu(menuMgr, viewer); } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#clearQueryContext() */ @Override public synchronized void clearQueryContext() { queryContext = null; } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#setColumnConfig(net.sf.logsaw.ui.editors.LogViewEditorColumnConfiguration) */ @Override public void setColumnConfig(LogViewEditorColumnConfiguration config) { Assert.isNotNull(config, "config"); //$NON-NLS-1$ columnConfig = config; updateColumns(config.getFields(), config.getWidths()); } private void updateColumns(List<ALogEntryField<?, ?>> newFields, int[] newWidths) { // Prevent flickering viewer.getTable().setRedraw(false); labelProvider.setFields(newFields.toArray(new ALogEntryField[newFields.size()])); // Dispose old columns TableColumn[] oldColumns = viewer.getTable().getColumns(); for (int i = 0; i < oldColumns.length; i++) { oldColumns[i].dispose(); } // Create icon column TableColumn col = new TableColumn(viewer.getTable(), SWT.NONE); col.setWidth(20); col.setResizable(false); int i = 0; for (ALogEntryField<?, ?> newField : newFields) { col = new TableColumn(viewer.getTable(), SWT.NONE); col.setText(newField.getLabel()); // Set order mark if (newField.equals(getLogResource().getDialect().getFieldProvider().getTimestampField())) { viewer.getTable().setSortColumn(col); viewer.getTable().setSortDirection(SWT.UP); } // Set width int newWidth = newWidths[i++]; if (newWidth > 0) { col.setWidth(newWidth); } else { col.setWidth(100); } col.addListener(SWT.Resize, new Listener() { /* (non-Javadoc) * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) */ @Override public void handleEvent(Event event) { saveColumnConfig(); } }); } viewer.refresh(true); viewer.getTable().setRedraw(true); } private void saveColumnConfig() { // Save column widths TableColumn[] columns = viewer.getTable().getColumns(); int[] newWidths = new int[columns.length - 1]; int i = 0; boolean first = true; for (TableColumn col : columns) { if (first) { // Ignore icon column first = false; continue; } newWidths[i++] = col.getWidth(); } columnConfig.update(columnConfig.getFields(), newWidths); } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#previousPage() */ @Override public void previousPage() { Assert.isNotNull(currentPage, "Current page must not be null"); //$NON-NLS-1$ Assert.isTrue(isPreviousPageAllowed(), "Current page number must be greater than 1"); //$NON-NLS-1$ goToPage(currentPageNumber - 1); } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#nextPage() */ @Override public void nextPage() { Assert.isNotNull(currentPage, "Current page must not be null"); //$NON-NLS-1$ Assert.isTrue(isNextPageAllowed(), "There must exist more items to display"); //$NON-NLS-1$ goToPage(currentPageNumber + 1); } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#isPreviousPageAllowed() */ @Override public boolean isPreviousPageAllowed() { return currentPageNumber > 1; } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#isNextPageAllowed() */ @Override public boolean isNextPageAllowed() { return (currentPage != null) && (currentPage.getTotalHits() > (currentPageNumber * pageSize)); } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#getFocusCellLogEntryField() */ @Override public ALogEntryField<?, ?> getFocusCellLogEntryField() { ViewerCell cell = focusCellManager.getFocusCell(); if ((cell != null) && (cell.getColumnIndex() > 0)) { return columnConfig.getFields().get(cell.getColumnIndex() - 1); } return null; } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#getFocusCellText() */ @Override public String getFocusCellText() { ALogEntryField<?, ?> fld = getFocusCellLogEntryField(); final LogEntry entry = getSelectedLogEntry(); if ((fld == null) || (entry == null)) { return ""; //$NON-NLS-1$ } final String[] ret = new String[1]; // Setup visitor ILogEntryFieldVisitor visitor = new ILogEntryFieldVisitor() { /* (non-Javadoc) * @see net.sf.logsaw.core.model.ILogEntryFieldVisitor#visit(net.sf.logsaw.core.model.StringLogEntryField) */ @Override public void visit(StringLogEntryField fld) { String value = entry.get(fld); if (value != null) { ret[0] = fld.toInputValue(value, getLogResource()); } } /* (non-Javadoc) * @see net.sf.logsaw.core.model.ILogEntryFieldVisitor#visit(net.sf.logsaw.core.model.LevelLogEntryField) */ @Override public void visit(LevelLogEntryField fld) { Level value = entry.get(fld); if (value != null) { ret[0] = fld.toInputValue(value, getLogResource()); } } /* (non-Javadoc) * @see net.sf.logsaw.core.model.ILogEntryFieldVisitor#visit(net.sf.logsaw.core.model.DateLogEntryField) */ @Override public void visit(DateLogEntryField fld) { Date value = entry.get(fld); if (value != null) { ret[0] = fld.toInputValue(value, getLogResource()); } } }; fld.visit(visitor); if ((ret[0] == null) || (ret[0].length() == 0)) { return ""; //$NON-NLS-1$ } return ret[0]; } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#getSelectedLogEntry() */ @Override public LogEntry getSelectedLogEntry() { ViewerCell cell = focusCellManager.getFocusCell(); if ((cell != null) && (cell.getColumnIndex() > 0)) { return (LogEntry) cell.getElement(); } return null; } /* (non-Javadoc) * @see net.sf.logsaw.ui.parts.IRefreshablePart#refresh() */ @Override public void refresh() { goToPage(((Integer) getSelectedPage()).intValue()); } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#goToPage(int) */ @Override public void goToPage(int pageNumber) { // Sanity checks if (pageNumber < 1) { pageNumber = 1; } if (currentPage == null) { Assert.isTrue(pageNumber == 1, "pageNumber must initially be set to 1"); //$NON-NLS-1$ } else { // Fallback to last page if page does not exist int pageCount = getPageCount(); if (pageNumber > pageCount) { pageNumber = pageCount; } } // Obtain fresh query context - if necessary synchronized (this) { if (queryContext == null) { queryContext = IndexPlugin.getDefault().getIndexService().createQueryContext(getLogResource()); } } try { currentPage = IndexPlugin.getDefault().getIndexService().query(queryContext, getRestrictable().getRestrictions(), (pageNumber - 1) * pageSize, pageSize); currentPageNumber = pageNumber; NumberFormat fmt = DecimalFormat.getInstance(); String header = currentPage.getTotalHits() == 0 ? Messages.LogViewEditor_pageHeader_empty : NLS.bind(Messages.LogViewEditor_pageHeader, new Object[] { fmt.format(currentPage.getOffset() + 1), fmt.format(currentPage.getOffset() + currentPage.getItems().size()), fmt.format(currentPage.getTotalHits()) }); if (!getRestrictable().getRestrictions().isEmpty()) { // Append suffix to show that filter is active header += Messages.LogViewEditor_pageHeader_filterSuffix; } resultLabel.setText(header); viewer.setInput(currentPage.getItems().toArray()); firePageChanged(); } catch (CoreException e) { // Log and show error UIPlugin.logAndShowError(e, false); } } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#getPageCount() */ @Override public int getPageCount() { if (currentPage == null) { // Avoid NPE return 1; } return (int) Math.max(Math.ceil(currentPage.getTotalHits() / (double) pageSize), 1); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.IPageChangeProvider#getSelectedPage() */ @Override public Object getSelectedPage() { return Integer.valueOf(currentPageNumber); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.IPageChangeProvider#addPageChangedListener(org.eclipse.jface.dialogs.IPageChangedListener) */ @Override public void addPageChangedListener(IPageChangedListener listener) { listeners.add(listener); } /* (non-Javadoc) * @see org.eclipse.jface.dialogs.IPageChangeProvider#removePageChangedListener(org.eclipse.jface.dialogs.IPageChangedListener) */ @Override public void removePageChangedListener(IPageChangedListener listener) { listeners.remove(listener); } private void firePageChanged() { PageChangedEvent e = new PageChangedEvent(this, getSelectedPage()); for (IPageChangedListener listener : listeners) { listener.pageChanged(e); } } /* (non-Javadoc) * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor) */ @Override public void doSave(IProgressMonitor monitor) { // n/a } /* (non-Javadoc) * @see org.eclipse.ui.part.EditorPart#doSaveAs() */ @Override public void doSaveAs() { // n/a } /* (non-Javadoc) * @see org.eclipse.ui.part.EditorPart#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput) */ @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { setPartName(input.getName()); setSite(site); setInput(input); } /* (non-Javadoc) * @see org.eclipse.ui.part.EditorPart#setInput(org.eclipse.ui.IEditorInput) */ @Override protected void setInput(IEditorInput input) { editorInput = input; super.setInput(input); } /* (non-Javadoc) * @see org.eclipse.ui.part.EditorPart#getEditorInput() */ @Override public IEditorInput getEditorInput() { // Return a fresh instance of IEditorInput return (IEditorInput) getLogResource().getAdapter(IEditorInput.class); } /* (non-Javadoc) * @see org.eclipse.ui.part.WorkbenchPart#dispose() */ @Override public void dispose() { super.dispose(); if (queryContext != null) { try { queryContext.close(); } catch (IOException e) { // Log error StatusManager.getManager().handle( new Status(IStatus.ERROR, UIPlugin.PLUGIN_ID, e.getLocalizedMessage(), e), StatusManager.LOG); } } } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#getLogResource() */ @Override public ILogResource getLogResource() { return (ILogResource) editorInput.getAdapter(ILogResource.class); } /* (non-Javadoc) * @see net.sf.logsaw.ui.editors.ILogViewEditor#getRestrictable() */ @Override public IRestrictable getRestrictable() { return (IRestrictable) editorInput.getAdapter(IRestrictable.class); } /* (non-Javadoc) * @see org.eclipse.ui.part.EditorPart#isDirty() */ @Override public boolean isDirty() { return false; } /* (non-Javadoc) * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed() */ @Override public boolean isSaveAsAllowed() { return false; } /* (non-Javadoc) * @see org.eclipse.ui.part.WorkbenchPart#setFocus() */ @Override public void setFocus() { viewer.getControl().setFocus(); } }