From dabcfe8c2bbbb0a6006958741ed0b8c0a09c875a Mon Sep 17 00:00:00 2001 From: Anton Leherbauer Date: Tue, 5 Dec 2006 13:33:45 +0000 Subject: [PATCH] Fix for Bug 151840 - Error in QuickOutline when sorting is enabled --- .../cdt/internal/ui/CPluginImages.java | 22 + .../ui/text/AbstractInformationControl.java | 776 ++++++++++++ .../ui/text/COutlineInformationControl.java | 1058 ++--------------- .../ui/text/CSourceViewerConfiguration.java | 27 +- 4 files changed, 901 insertions(+), 982 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/AbstractInformationControl.java diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java index 5409ca5da94..afd04327a06 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CPluginImages.java @@ -305,6 +305,28 @@ public class CPluginImages { } } + /** + * Sets the three image descriptors for enabled, disabled, and hovered to an action. The actions + * are retrieved from the *tool16 folders. + * + * @param action the action + * @param iconName the icon name + */ + public static void setToolImageDescriptors(IAction action, String iconName) { + setImageDescriptors(action, T_TOOL, iconName); + } + + /** + * Sets the three image descriptors for enabled, disabled, and hovered to an action. The actions + * are retrieved from the *lcl16 folders. + * + * @param action the action + * @param iconName the icon name + */ + public static void setLocalImageDescriptors(IAction action, String iconName) { + setImageDescriptors(action, T_LCL, iconName); + } + /** * Sets all available image descriptors for the given action. */ diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/AbstractInformationControl.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/AbstractInformationControl.java new file mode 100644 index 00000000000..9cef71da331 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/AbstractInformationControl.java @@ -0,0 +1,776 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.text; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.dialogs.PopupDialog; +import org.eclipse.jface.text.IInformationControl; +import org.eclipse.jface.text.IInformationControlExtension; +import org.eclipse.jface.text.IInformationControlExtension2; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.ViewerFilter; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.MouseAdapter; +import org.eclipse.swt.events.MouseEvent; +import org.eclipse.swt.events.MouseMoveListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Item; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.IEditorPart; + +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.core.model.IParent; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.ui.actions.CustomFiltersActionGroup; + +import org.eclipse.cdt.internal.ui.util.EditorUtility; +import org.eclipse.cdt.internal.ui.util.StringMatcher; + +/** + * Abstract class for "quick" views in light-weight controls. + * + * @since 4.0 + */ +public abstract class AbstractInformationControl extends PopupDialog implements IInformationControl, IInformationControlExtension, IInformationControlExtension2, DisposeListener { + + /** + * The NamePatternFilter selects the elements which + * match the given string patterns. + */ + protected class NamePatternFilter extends ViewerFilter { + + public NamePatternFilter() { + } + + /* + * Method declared on ViewerFilter. + */ + public boolean select(Viewer viewer, Object parentElement, Object element) { + StringMatcher matcher= getMatcher(); + if (matcher == null || !(viewer instanceof TreeViewer)) + return true; + TreeViewer treeViewer= (TreeViewer) viewer; + + String matchName= ((ILabelProvider) treeViewer.getLabelProvider()).getText(element); + if (matchName != null && matcher.match(matchName)) + return true; + + return hasUnfilteredChild(treeViewer, element); + } + + private boolean hasUnfilteredChild(TreeViewer viewer, Object element) { + if (element instanceof IParent) { + Object[] children= ((ITreeContentProvider) viewer.getContentProvider()).getChildren(element); + for (int i= 0; i < children.length; i++) + if (select(viewer, element, children[i])) + return true; + } + return false; + } + } + + /** The control's text widget */ + private Text fFilterText; + /** The control's tree widget */ + private TreeViewer fTreeViewer; + /** The current string matcher */ + protected StringMatcher fStringMatcher; +// private ICommand fInvokingCommand; +// private KeySequence[] fInvokingCommandKeySequences; + + /** + * Fields that support the dialog menu + * - now appended to framework menu + */ + private Composite fViewMenuButtonComposite; + + private CustomFiltersActionGroup fCustomFiltersActionGroup; + +// private IKeyBindingService fKeyBindingService; +// private String[] fKeyBindingScopes; + private IAction fShowViewMenuAction; +// private HandlerSubmission fShowViewMenuHandlerSubmission; + + /** + * Field for tree style since it must be remembered by the instance. + */ + private int fTreeStyle; + + /** + * Creates a tree information control with the given shell as parent. The given + * styles are applied to the shell and the tree widget. + * + * @param parent the parent shell + * @param shellStyle the additional styles for the shell + * @param treeStyle the additional styles for the tree widget + * @param invokingCommandId the id of the command that invoked this control or null + * @param showStatusField true iff the control has a status field at the bottom + */ + public AbstractInformationControl(Shell parent, int shellStyle, int treeStyle, String invokingCommandId, boolean showStatusField) { + super(parent, shellStyle, true, true, true, true, null, null); + if (invokingCommandId != null) { +// ICommandManager commandManager= PlatformUI.getWorkbench().getCommandSupport().getCommandManager(); +// fInvokingCommand= commandManager.getCommand(invokingCommandId); +// if (fInvokingCommand != null && !fInvokingCommand.isDefined()) +// fInvokingCommand= null; +// else +// // Pre-fetch key sequence - do not change because scope will change later. +// getInvokingCommandKeySequences(); + } + fTreeStyle= treeStyle; + // Title and status text must be set to get the title label created, so force empty values here. + if (hasHeader()) + setTitleText(""); //$NON-NLS-1$ + setInfoText(""); // //$NON-NLS-1$ + + // Create all controls early to preserve the life cycle of the original implementation. + create(); + + // Status field text can only be computed after widgets are created. + setInfoText(getStatusFieldText()); + } + + /** + * Create the main content for this information control. + * + * @param parent The parent composite + * @return The control representing the main content. + * + */ + protected Control createDialogArea(Composite parent) { + fTreeViewer= createTreeViewer(parent, fTreeStyle); + + fCustomFiltersActionGroup= new CustomFiltersActionGroup(getId(), fTreeViewer); + + final Tree tree= fTreeViewer.getTree(); + tree.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + if (e.character == 0x1B) // ESC + dispose(); + } + public void keyReleased(KeyEvent e) { + // do nothing + } + }); + + tree.addSelectionListener(new SelectionListener() { + public void widgetSelected(SelectionEvent e) { + // do nothing + } + public void widgetDefaultSelected(SelectionEvent e) { + gotoSelectedElement(); + } + }); + + tree.addMouseMoveListener(new MouseMoveListener() { + TreeItem fLastItem= null; + public void mouseMove(MouseEvent e) { + if (tree.equals(e.getSource())) { + Object o= tree.getItem(new Point(e.x, e.y)); + if (o instanceof TreeItem) { + if (!o.equals(fLastItem)) { + fLastItem= (TreeItem)o; + tree.setSelection(new TreeItem[] { fLastItem }); + } else if (e.y < tree.getItemHeight() / 4) { + // Scroll up + Point p= tree.toDisplay(e.x, e.y); + Item item= fTreeViewer.scrollUp(p.x, p.y); + if (item instanceof TreeItem) { + fLastItem= (TreeItem)item; + tree.setSelection(new TreeItem[] { fLastItem }); + } + } else if (e.y > tree.getBounds().height - tree.getItemHeight() / 4) { + // Scroll down + Point p= tree.toDisplay(e.x, e.y); + Item item= fTreeViewer.scrollDown(p.x, p.y); + if (item instanceof TreeItem) { + fLastItem= (TreeItem)item; + tree.setSelection(new TreeItem[] { fLastItem }); + } + } + } + } + } + }); + + tree.addMouseListener(new MouseAdapter() { + public void mouseUp(MouseEvent e) { + + if (tree.getSelectionCount() < 1) + return; + + if (e.button != 1) + return; + + if (tree.equals(e.getSource())) { + Object o= tree.getItem(new Point(e.x, e.y)); + TreeItem selection= tree.getSelection()[0]; + if (selection.equals(o)) + gotoSelectedElement(); + } + } + }); + + installFilter(); + + addDisposeListener(this); + return fTreeViewer.getControl(); + } + + /** + * Creates a tree information control with the given shell as parent. The given + * styles are applied to the shell and the tree widget. + * + * @param parent the parent shell + * @param shellStyle the additional styles for the shell + * @param treeStyle the additional styles for the tree widget + */ + public AbstractInformationControl(Shell parent, int shellStyle, int treeStyle) { + this(parent, shellStyle, treeStyle, null, false); + } + + protected abstract TreeViewer createTreeViewer(Composite parent, int style); + + /** + * Returns the name of the dialog settings section. + * + * @return the name of the dialog settings section + */ + protected abstract String getId(); + + protected TreeViewer getTreeViewer() { + return fTreeViewer; + } + + /** + * Returns true if the control has a header, false otherwise. + *

+ * The default is to return false. + *

+ * + * @return true if the control has a header + */ + protected boolean hasHeader() { + // default is to have no header + return false; + } + + protected Text getFilterText() { + return fFilterText; + } + + protected Text createFilterText(Composite parent) { + fFilterText= new Text(parent, SWT.NONE); + + GridData data= new GridData(GridData.FILL_HORIZONTAL); + GC gc= new GC(parent); + gc.setFont(parent.getFont()); + FontMetrics fontMetrics= gc.getFontMetrics(); + gc.dispose(); + + data.heightHint= Dialog.convertHeightInCharsToPixels(fontMetrics, 1); + data.horizontalAlignment= GridData.FILL; + data.verticalAlignment= GridData.CENTER; + fFilterText.setLayoutData(data); + + fFilterText.addKeyListener(new KeyListener() { + public void keyPressed(KeyEvent e) { + if (e.keyCode == 0x0D) // return + gotoSelectedElement(); + if (e.keyCode == SWT.ARROW_DOWN) + fTreeViewer.getTree().setFocus(); + if (e.keyCode == SWT.ARROW_UP) + fTreeViewer.getTree().setFocus(); + if (e.character == 0x1B) // ESC + dispose(); + } + public void keyReleased(KeyEvent e) { + // do nothing + } + }); + + return fFilterText; + } + + protected void createHorizontalSeparator(Composite parent) { + Label separator= new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT); + separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + } + + protected void updateStatusFieldText() { + setInfoText(getStatusFieldText()); + } + + /** + * Handles click in status field. + *

+ * Default does nothing. + *

+ */ + protected void handleStatusFieldClicked() { + } + + protected String getStatusFieldText() { + return ""; //$NON-NLS-1$ + } + + private void installFilter() { + fFilterText.setText(""); //$NON-NLS-1$ + + fFilterText.addModifyListener(new ModifyListener() { + public void modifyText(ModifyEvent e) { + String text= ((Text) e.widget).getText(); + int length= text.length(); + if (length > 0 && text.charAt(length -1 ) != '*') { + text= text + '*'; + } + setMatcherString(text, true); + } + }); + } + + /** + * The string matcher has been modified. The default implementation + * refreshes the view and selects the first matched element + */ + protected void stringMatcherUpdated() { + // refresh viewer to re-filter + fTreeViewer.getControl().setRedraw(false); + fTreeViewer.refresh(); + fTreeViewer.expandAll(); + selectFirstMatch(); + fTreeViewer.getControl().setRedraw(true); + } + + /** + * Sets the patterns to filter out for the receiver. + *

+ * The following characters have special meaning: + * ? => any character + * * => any string + *

+ * + * @param pattern the pattern + * @param update true if the viewer should be updated + */ + protected void setMatcherString(String pattern, boolean update) { + if (pattern.length() == 0) { + fStringMatcher= null; + } else { + boolean ignoreCase= pattern.toLowerCase().equals(pattern); + fStringMatcher= new StringMatcher(pattern, ignoreCase, false); + } + + if (update) + stringMatcherUpdated(); + } + + protected StringMatcher getMatcher() { + return fStringMatcher; + } + + /** + * Implementers can modify + * + * @return the selected element + */ + protected Object getSelectedElement() { + if (fTreeViewer == null) + return null; + + return ((IStructuredSelection) fTreeViewer.getSelection()).getFirstElement(); + } + + private void gotoSelectedElement() { + Object selectedElement= getSelectedElement(); + if (selectedElement != null) { + try { + dispose(); + IEditorPart part= EditorUtility.openInEditor(selectedElement, true); + if (part != null && selectedElement instanceof ICElement) + EditorUtility.revealInEditor(part, (ICElement) selectedElement); + } catch (CoreException ex) { + CUIPlugin.getDefault().log(ex); + } + } + } + + /** + * Selects the first element in the tree which + * matches the current filter pattern. + */ + protected void selectFirstMatch() { + Tree tree= fTreeViewer.getTree(); + Object element= findElement(tree.getItems()); + if (element != null) + fTreeViewer.setSelection(new StructuredSelection(element), true); + else + fTreeViewer.setSelection(StructuredSelection.EMPTY); + } + + private ICElement findElement(TreeItem[] items) { + ILabelProvider labelProvider= (ILabelProvider)fTreeViewer.getLabelProvider(); + for (int i= 0; i < items.length; i++) { + ICElement element= (ICElement)items[i].getData(); + if (fStringMatcher == null) + return element; + + if (element != null) { + String label= labelProvider.getText(element); + if (fStringMatcher.match(label)) + return element; + } + + element= findElement(items[i].getItems()); + if (element != null) + return element; + } + return null; + } + + /** + * {@inheritDoc} + */ + public void setInformation(String information) { + // this method is ignored, see IInformationControlExtension2 + } + + /** + * {@inheritDoc} + */ + public abstract void setInput(Object information); + + /** + * Fills the view menu. + * Clients can extend or override. + * + * @param viewMenu the menu manager that manages the menu + */ + protected void fillViewMenu(IMenuManager viewMenu) { + fCustomFiltersActionGroup.fillViewMenu(viewMenu); + } + + /* + * Overridden to call the old framework method. + * + * @see org.eclipse.jface.dialogs.PopupDialog#fillDialogMenu(IMenuManager) + * + */ + protected void fillDialogMenu(IMenuManager dialogMenu) { + super.fillDialogMenu(dialogMenu); + fillViewMenu(dialogMenu); + } + + protected void inputChanged(Object newInput, Object newSelection) { + fFilterText.setText(""); //$NON-NLS-1$ + fTreeViewer.setInput(newInput); + if (newSelection != null) { + fTreeViewer.setSelection(new StructuredSelection(newSelection)); + } + } + + /** + * {@inheritDoc} + */ + public void setVisible(boolean visible) { + if (visible) { + addHandlerAndKeyBindingSupport(); + open(); + } else { + removeHandlerAndKeyBindingSupport(); + saveDialogBounds(getShell()); + getShell().setVisible(false); + removeHandlerAndKeyBindingSupport(); + } + } + + /** + * {@inheritDoc} + */ + public final void dispose() { + close(); + } + + /** + * {@inheritDoc} + * @param event can be null + *

+ * Subclasses may extend. + *

+ */ + public void widgetDisposed(DisposeEvent event) { + removeHandlerAndKeyBindingSupport(); + fTreeViewer= null; + fFilterText= null; +// fKeyBindingService= null; + } + + /** + * Adds handler and key binding support. + */ + protected void addHandlerAndKeyBindingSupport() { +// // Remember current scope and then set window context. +// if (fKeyBindingScopes == null && fKeyBindingService != null) { +// fKeyBindingScopes= fKeyBindingService.getScopes(); +// fKeyBindingService.setScopes(new String[] { IWorkbenchContextSupport.CONTEXT_ID_WINDOW }); +// } +// +// // Register action with command support +// if (fShowViewMenuHandlerSubmission == null) { +// fShowViewMenuHandlerSubmission= new HandlerSubmission(null, getShell(), null, fShowViewMenuAction.getActionDefinitionId(), new ActionHandler(fShowViewMenuAction), Priority.MEDIUM); +// PlatformUI.getWorkbench().getCommandSupport().addHandlerSubmission(fShowViewMenuHandlerSubmission); +// } + } + + /** + * Removes handler and key binding support. + */ + protected void removeHandlerAndKeyBindingSupport() { +// // Remove handler submission +// if (fShowViewMenuHandlerSubmission != null) +// PlatformUI.getWorkbench().getCommandSupport().removeHandlerSubmission(fShowViewMenuHandlerSubmission); +// +// // Restore editor's key binding scope +// if (fKeyBindingService != null && fKeyBindingScopes != null) { +// fKeyBindingService.setScopes(fKeyBindingScopes); +// fKeyBindingScopes= null; +// } + } + + /** + * {@inheritDoc} + */ + public boolean hasContents() { + return fTreeViewer != null && fTreeViewer.getInput() != null; + } + + /** + * {@inheritDoc} + */ + public void setSizeConstraints(int maxWidth, int maxHeight) { + // ignore + } + + /** + * {@inheritDoc} + */ + public Point computeSizeHint() { + // return the shell's size - note that it already has the persisted size if persisting + // is enabled. + return getShell().getSize(); + } + + /** + * {@inheritDoc} + */ + public void setLocation(Point location) { + /* + * If the location is persisted, it gets managed by PopupDialog - fine. Otherwise, the location is + * computed in Window#getInitialLocation, which will center it in the parent shell / main + * monitor, which is wrong for two reasons: + * - we want to center over the editor / subject control, not the parent shell + * - the center is computed via the initalSize, which may be also wrong since the size may + * have been updated since via min/max sizing of AbstractInformationControlManager. + * In that case, override the location with the one computed by the manager. Note that + * the call to constrainShellSize in PopupDialog.open will still ensure that the shell is + * entirely visible. + */ + if (!getPersistBounds() || getDialogSettings() == null) + getShell().setLocation(location); + } + + /** + * {@inheritDoc} + */ + public void setSize(int width, int height) { + getShell().setSize(width, height); + } + + /** + * {@inheritDoc} + */ + public void addDisposeListener(DisposeListener listener) { + getShell().addDisposeListener(listener); + } + + /** + * {@inheritDoc} + */ + public void removeDisposeListener(DisposeListener listener) { + getShell().removeDisposeListener(listener); + } + + /** + * {@inheritDoc} + */ + public void setForegroundColor(Color foreground) { + applyForegroundColor(foreground, getContents()); + } + + /** + * {@inheritDoc} + */ + public void setBackgroundColor(Color background) { + applyBackgroundColor(background, getContents()); + } + + /** + * {@inheritDoc} + */ + public boolean isFocusControl() { + return fTreeViewer.getControl().isFocusControl() || fFilterText.isFocusControl(); + } + + /** + * {@inheritDoc} + */ + public void setFocus() { + getShell().forceFocus(); + fFilterText.setFocus(); + } + + /** + * {@inheritDoc} + */ + public void addFocusListener(FocusListener listener) { + getShell().addFocusListener(listener); + } + + /** + * {@inheritDoc} + */ + public void removeFocusListener(FocusListener listener) { + getShell().removeFocusListener(listener); + } + +// final protected ICommand getInvokingCommand() { +// return fInvokingCommand; +// } + +// final protected KeySequence[] getInvokingCommandKeySequences() { +// if (fInvokingCommandKeySequences == null) { +// if (getInvokingCommand() != null) { +// List list= getInvokingCommand().getKeySequenceBindings(); +// if (!list.isEmpty()) { +// fInvokingCommandKeySequences= new KeySequence[list.size()]; +// for (int i= 0; i < fInvokingCommandKeySequences.length; i++) { +// fInvokingCommandKeySequences[i]= ((IKeySequenceBinding) list.get(i)).getKeySequence(); +// } +// return fInvokingCommandKeySequences; +// } +// } +// } +// return fInvokingCommandKeySequences; +// } + + /* + * @see org.eclipse.jface.dialogs.PopupDialog#getDialogSettings() + */ + protected IDialogSettings getDialogSettings() { + String sectionName= getId(); + + IDialogSettings settings= CUIPlugin.getDefault().getDialogSettings().getSection(sectionName); + if (settings == null) + settings= CUIPlugin.getDefault().getDialogSettings().addNewSection(sectionName); + + return settings; + } + + /* + * Overridden to insert the filter text into the title and menu area. + */ + protected Control createTitleMenuArea(Composite parent) { + fViewMenuButtonComposite= (Composite) super.createTitleMenuArea(parent); + + // If there is a header, then the filter text must be created + // underneath the title and menu area. + + if (hasHeader()) { + fFilterText= createFilterText(parent); + } + + // Create a key binding for showing the dialog menu + // Key binding service +// IWorkbenchPart part= CUIPlugin.getActivePage().getActivePart(); +// IWorkbenchPartSite site= part.getSite(); +// fKeyBindingService= site.getKeyBindingService(); + + // Create show view menu action + fShowViewMenuAction= new Action("showViewMenu") { //$NON-NLS-1$ + /* + * @see org.eclipse.jface.action.Action#run() + */ + public void run() { + showDialogMenu(); + } + }; + fShowViewMenuAction.setEnabled(true); + fShowViewMenuAction.setActionDefinitionId("org.eclipse.ui.window.showViewMenu"); //$NON-NLS-1$ + + addHandlerAndKeyBindingSupport(); + + return fViewMenuButtonComposite; + } + + /* + * Overridden to insert the filter text into the title control + * if there is no header specified. + * + */ + protected Control createTitleControl(Composite parent) { + if (hasHeader()) { + return super.createTitleControl(parent); + } + fFilterText= createFilterText(parent); + return fFilterText; + } + + /* + * @see org.eclipse.jface.dialogs.PopupDialog#setTabOrder(org.eclipse.swt.widgets.Composite) + */ + protected void setTabOrder(Composite composite) { + if (hasHeader()) { + composite.setTabList(new Control[] { fFilterText, fTreeViewer.getTree() }); + } else { + fViewMenuButtonComposite.setTabList(new Control[] { fFilterText }); + composite.setTabList(new Control[] { fViewMenuButtonComposite, fTreeViewer.getTree() }); + } + } +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/COutlineInformationControl.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/COutlineInformationControl.java index fd4764901de..5d68ab98f26 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/COutlineInformationControl.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/COutlineInformationControl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005 QNX Software Systems and others. + * Copyright (c) 2005, 2006 QNX Software Systems 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 @@ -8,88 +8,30 @@ * Contributors: * QNX Software Systems - initial API and implementation * Sergey Prigogin, Google + * Anton Leherbauer (Wind River Systems) *******************************************************************************/ -/* - * COutlineInformationControl.java 2004-12-14 / 08:17:41 - - * $Revision: 1.6 $ $Date: 2006/09/12 06:50:49 $ - * - * @author P.Tomaszewski - */ package org.eclipse.cdt.internal.ui.text; -import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; -import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.Separator; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.dialogs.IDialogSettings; -import org.eclipse.jface.text.IInformationControl; -import org.eclipse.jface.text.IInformationControlExtension; -import org.eclipse.jface.text.IInformationControlExtension2; -import org.eclipse.jface.text.IInformationControlExtension3; import org.eclipse.jface.viewers.AbstractTreeViewer; import org.eclipse.jface.viewers.IContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.jface.viewers.Viewer; -import org.eclipse.jface.viewers.ViewerSorter; -import org.eclipse.swt.SWT; -import org.eclipse.swt.events.ControlAdapter; -import org.eclipse.swt.events.ControlEvent; -import org.eclipse.swt.events.ControlListener; -import org.eclipse.swt.events.DisposeListener; -import org.eclipse.swt.events.FocusListener; -import org.eclipse.swt.events.KeyEvent; -import org.eclipse.swt.events.KeyListener; -import org.eclipse.swt.events.ModifyEvent; -import org.eclipse.swt.events.ModifyListener; -import org.eclipse.swt.events.MouseAdapter; -import org.eclipse.swt.events.MouseEvent; -import org.eclipse.swt.events.MouseListener; -import org.eclipse.swt.events.MouseMoveListener; -import org.eclipse.swt.events.SelectionAdapter; -import org.eclipse.swt.events.SelectionEvent; -import org.eclipse.swt.events.SelectionListener; -import org.eclipse.swt.events.ShellAdapter; -import org.eclipse.swt.events.ShellEvent; -import org.eclipse.swt.events.ShellListener; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.FontMetrics; -import org.eclipse.swt.graphics.GC; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Display; -import org.eclipse.swt.widgets.Event; -import org.eclipse.swt.widgets.Item; -import org.eclipse.swt.widgets.Label; -import org.eclipse.swt.widgets.Layout; -import org.eclipse.swt.widgets.Listener; -import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; -import org.eclipse.swt.widgets.Text; -import org.eclipse.swt.widgets.ToolBar; -import org.eclipse.swt.widgets.ToolItem; -import org.eclipse.swt.widgets.Tracker; import org.eclipse.swt.widgets.Tree; -import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.PlatformUI; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ITranslationUnit; -import org.eclipse.cdt.ui.CElementGrouping; -import org.eclipse.cdt.ui.CUIPlugin; - -import org.eclipse.cdt.internal.core.model.CElement; import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.cdt.internal.ui.ICHelpContextIds; import org.eclipse.cdt.internal.ui.actions.ActionMessages; -import org.eclipse.cdt.internal.ui.actions.OpenActionUtil; import org.eclipse.cdt.internal.ui.editor.CContentOutlinerProvider; import org.eclipse.cdt.internal.ui.util.ProblemTreeViewer; import org.eclipse.cdt.internal.ui.viewsupport.AppearanceAwareLabelProvider; @@ -101,70 +43,19 @@ import org.eclipse.cdt.internal.ui.viewsupport.StandardCElementLabelProvider; * Control which shows outline information in C/C++ editor. Based on * AbstracInformationContol/JavaOutlineInformationControl from JDT. * - * TODO: Sorting. - * * @author P.Tomaszewski */ -public class COutlineInformationControl implements IInformationControl, - IInformationControlExtension, IInformationControlExtension2, - IInformationControlExtension3 { +public class COutlineInformationControl extends AbstractInformationControl { - /** If this option is set, location is not restored. */ - private static final String STORE_RESTORE_SIZE= "ENABLE_RESTORE_SIZE"; //$NON-NLS-1$ - /** If this option is set, size is not restore. */ - private static final String STORE_RESTORE_LOCATION= "ENABLE_RESTORE_LOCATION"; //$NON-NLS-1$ - /** If this option is set, sort is done. */ - private static final String STORE_SORT_ENABLED = "ENABLE_SORT"; //$NON-NLS-1$ - - /** Border thickness in pixels. */ - private static final int BORDER = 1; - /** Right margin in pixels. */ - private static final int RIGHT_MARGIN = 3; - /** Minimum width set by setSizeConstrains to tree viewer. */ - private static final int MIN_WIDTH = 300; private static final int TEXT_FLAGS = AppearanceAwareLabelProvider.DEFAULT_TEXTFLAGS | CElementLabels.F_APP_TYPE_SIGNATURE | CElementLabels.M_APP_RETURNTYPE; private static final int IMAGE_FLAGS = AppearanceAwareLabelProvider.DEFAULT_IMAGEFLAGS; private ICElement fInput = null; - /** Shell for this control. */ - Shell fShell; - /** Control's composite. */ - Composite fComposite; - /** Tree viewer used to display outline. */ - TreeViewer fTreeViewer; - /** Text control for filter. */ - Text fFilterText; - /** Content provider for tree control. */ - IContentProvider fTreeContentProvider; + private IContentProvider fOutlineContentProvider; - /** Sorter for tree viewer. */ - OutlineSorter fSorter; - - /** Control bounds. */ - Rectangle fBounds; - /** Control trim. */ - Rectangle fTrim; - - /** This prevents to notify listener when it is adding. */ - boolean fIsDeactivationActive; - - /** Deactivation adapter. */ - private Listener fDeactivateListener; - /** Shell adapter, used for control deactivation. */ - private ShellListener fShellListener; - /** Control adapter for shell, used in resize action. */ - private ControlListener fControlListener; - - /** Should outline be sorted. */ - boolean fSort = true; - - /** Tool bar displayed on the top of the outline. */ - ToolBar fToolBar; - /** Composite for tool bar. */ - private Composite fToolbarComposite; - /** Menu manager for options menu. */ - private MenuManager fViewMenuManager; + /** The action to toggle sorting */ + private LexicalSortingAction fSortingAction; /** * Creates new outline control. @@ -177,14 +68,33 @@ public class COutlineInformationControl implements IInformationControl, * Style of the tree viewer. */ public COutlineInformationControl(Shell parent, int shellStyle, int treeStyle) { - super(); - createShell(parent, shellStyle); - createComposite(); - createToolbar(); - createHorizontalSeparator(); - createTreeeViewer(treeStyle); + super(parent, shellStyle, treeStyle, null, false); } + /** + * {@inheritDoc} + */ + protected TreeViewer createTreeViewer(Composite parent, int treeStyle) { + TreeViewer treeViewer = new ProblemTreeViewer(parent, treeStyle); + final Tree tree = treeViewer.getTree(); + tree.setLayoutData(new GridData(GridData.FILL_BOTH)); + fOutlineContentProvider = new CContentOutlinerProvider(treeViewer); + treeViewer.setContentProvider(fOutlineContentProvider); + fSortingAction= new LexicalSortingAction(treeViewer); + treeViewer.addFilter(new NamePatternFilter()); + treeViewer.setLabelProvider(new DecoratingCLabelProvider( + new StandardCElementLabelProvider(TEXT_FLAGS, IMAGE_FLAGS), true)); + treeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); + return treeViewer; + } + + /* + * @see org.eclipse.cdt.internal.ui.text.AbstractInformationControl#getId() + */ + protected String getId() { + return "org.eclipse.cdt.internal.ui.text.QuickOutline"; //$NON-NLS-1$ + } + /** * {@inheritDoc} */ @@ -201,857 +111,83 @@ public class COutlineInformationControl implements IInformationControl, inputChanged(fInput, information); } - protected void inputChanged(Object newInput, Object newSelection) { - fFilterText.setText(""); //$NON-NLS-1$ - fTreeViewer.setInput(newInput); - if (newSelection != null) { - fTreeViewer.setSelection(new StructuredSelection(newSelection)); - } - } - - /** - * @return the selected element + /* + * @see org.eclipse.jdt.internal.ui.text.AbstractInformationControl#fillViewMenu(org.eclipse.jface.action.IMenuManager) */ - protected Object getSelectedElement() { - if (fTreeViewer == null) - return null; + protected void fillViewMenu(IMenuManager viewMenu) { + super.fillViewMenu(viewMenu); + + viewMenu.add(new Separator("Sorters")); //$NON-NLS-1$ + viewMenu.add(fSortingAction); - return ((IStructuredSelection) fTreeViewer.getSelection()).getFirstElement(); } - private void gotoSelectedElement() { - Object selectedElement= getSelectedElement(); - if (selectedElement != null) { - try { - dispose(); - OpenActionUtil.open(selectedElement, true); - } catch (CoreException e) { - CUIPlugin.getDefault().log(e); + private class LexicalCSorter extends ViewerComparator { + public boolean isSorterProperty(Object element, Object property) { + return true; + } + + public int category(Object obj) { + if (obj instanceof ICElement) { + ICElement elem= (ICElement)obj; + switch (elem.getElementType()) { + case ICElement.C_MACRO: return 1; + case ICElement.C_INCLUDE: return 2; + + case ICElement.C_CLASS: return 3; + case ICElement.C_STRUCT: return 4; + case ICElement.C_UNION: return 5; + + case ICElement.C_FIELD: return 6; + case ICElement.C_FUNCTION: return 7; + } + } + return 0; } } - /** - * @see org.eclipse.jface.text.IInformationControl#setInformation(java.lang.String) - */ - public void setInformation(String information) { - // Does not need implementation. - } - - /** - * @see org.eclipse.jface.text.IInformationControl#setSizeConstraints(int, - * int) - */ - public void setSizeConstraints(int maxWidth, int maxHeight) { - // Copied from AbstractInformationContol. - if (maxWidth > -1 && maxHeight > -1) { - final GridData gd = new GridData(GridData.FILL_BOTH); - if (maxWidth > -1) { - if (maxWidth < MIN_WIDTH) { - gd.widthHint = MIN_WIDTH; - } else { - gd.widthHint = maxWidth; - } - } - if (maxHeight > -1) { - gd.heightHint = maxHeight; - } - - fTreeViewer.getTree().setLayoutData(gd); - } - } - - /** - * @see org.eclipse.jface.text.IInformationControl#computeSizeHint() - */ - public Point computeSizeHint() { - return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT); - } - - /** - * @see org.eclipse.jface.text.IInformationControl#setVisible(boolean) - */ - public void setVisible(boolean visible) { - if (visible || fIsDeactivationActive) { - fShell.setVisible(visible); - } - } - - /** - * @see org.eclipse.jface.text.IInformationControl#setSize(int, int) - */ - public void setSize(int width, int height) { - fShell.setSize(width, height); - } - - /** - * @see org.eclipse.jface.text.IInformationControl#setLocation(org.eclipse.swt.graphics.Point) - */ - public void setLocation(Point location) { - fTrim = fShell.computeTrim(0, 0, 0, 0); - Point compositeLocation = fComposite.getLocation(); - location.x += fTrim.x - compositeLocation.x; - location.y += fTrim.y - compositeLocation.y; - fShell.setLocation(location); - } - - /** - * @see org.eclipse.jface.text.IInformationControl#dispose() - */ - public void dispose() { - if (fShell != null && !fShell.isDisposed()) { - fShell.removeShellListener(fShellListener); - fShell.removeListener(SWT.Deactivate, fDeactivateListener); - fShell.dispose(); - fFilterText.dispose(); - fComposite.dispose(); - } else { - fShell = null; - fComposite = null; - fTreeViewer = null; - fFilterText = null; - fDeactivateListener = null; - fShellListener = null; - } - } - - /** - * @see org.eclipse.jface.text.IInformationControl#addDisposeListener(org.eclipse.swt.events.DisposeListener) - */ - public void addDisposeListener(DisposeListener listener) { - fShell.addDisposeListener(listener); - } - - /** - * @see org.eclipse.jface.text.IInformationControl#removeDisposeListener(org.eclipse.swt.events.DisposeListener) - */ - public void removeDisposeListener(DisposeListener listener) { - fShell.removeDisposeListener(listener); - } - - /** - * @see org.eclipse.jface.text.IInformationControl#setForegroundColor(org.eclipse.swt.graphics.Color) - */ - public void setForegroundColor(Color foreground) { - fTreeViewer.getTree().setForeground(foreground); - fFilterText.setForeground(foreground); - fComposite.setForeground(foreground); - } - - /** - * @see org.eclipse.jface.text.IInformationControl#setBackgroundColor(org.eclipse.swt.graphics.Color) - */ - public void setBackgroundColor(Color background) { - fTreeViewer.getTree().setBackground(background); - fFilterText.setBackground(background); - fComposite.setBackground(background); - } - - /** - * @see org.eclipse.jface.text.IInformationControl#isFocusControl() - */ - public boolean isFocusControl() { - return fTreeViewer.getControl().isFocusControl() - || fFilterText.isFocusControl(); - } - - /** - * @see org.eclipse.jface.text.IInformationControl#setFocus() - */ - public void setFocus() { - fShell.forceFocus(); - fFilterText.setFocus(); - } - - /** - * @see org.eclipse.jface.text.IInformationControl#addFocusListener(org.eclipse.swt.events.FocusListener) - */ - public void addFocusListener(FocusListener listener) { - fShell.addFocusListener(listener); - } - - /** - * @see org.eclipse.jface.text.IInformationControl#removeFocusListener(org.eclipse.swt.events.FocusListener) - */ - public void removeFocusListener(FocusListener listener) { - fShell.removeFocusListener(listener); - } - - /** - * @see org.eclipse.jface.text.IInformationControlExtension#hasContents() - */ - public boolean hasContents() { - return fTreeViewer != null - && ((Tree) fTreeViewer.getControl()).getItemCount() > 0; - } - - /** - * @see org.eclipse.jface.text.IInformationControlExtension3#getBounds() - */ - public Rectangle getBounds() { - return fBounds; - } - - /** - * @see org.eclipse.jface.text.IInformationControlExtension3#computeTrim() - */ - public Rectangle computeTrim() { - // Copied from AbstractInformationControl. - if (fTrim != null) { - return fTrim; - } - return new Rectangle(0, 0, 0, 0); - } - - /** - * @see org.eclipse.jface.text.IInformationControlExtension3#restoresLocation() - */ - public boolean restoresLocation() { - return getSettings().getBoolean(STORE_RESTORE_LOCATION); - } - - /** - * @see org.eclipse.jface.text.IInformationControlExtension3#restoresSize() - */ - public boolean restoresSize() { - return getSettings().getBoolean(STORE_RESTORE_SIZE); - } - - /** - * Returns view manager instance. If instance does not exit it is created. - * @return View manager. - */ - MenuManager getViewMenuManager() { - if (fViewMenuManager == null) { - fViewMenuManager= new MenuManager(); - fViewMenuManager.add(new SortAction()); - fViewMenuManager.add(new Separator()); - fViewMenuManager.add(new RememberBoundsAction()); - fViewMenuManager.add(new MoveAction()); - } - return fViewMenuManager; - } - - /** - * Creates shell for outline control. - * - * @param parent - * Parent shell. - * @param shellStyle - * Shell style. - */ - private void createShell(Shell parent, int shellStyle) { - fShell = new Shell(parent, shellStyle); - final Display display = fShell.getDisplay(); - fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); - final int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER; - fShell.setLayout(new BorderFillLayout(border)); - createDeactivationListener(); - fShell.addListener(SWT.Deactivate, fDeactivateListener); - fIsDeactivationActive = true; - createShellListener(); - fShell.addShellListener(fShellListener); - createControlListener(); - fShell.addControlListener(fControlListener); - } - - /** - * Creates composite of the outline control. - * - */ - private void createComposite() { - fComposite = new Composite(fShell, SWT.RESIZE); - GridLayout layout = new GridLayout(1, false); - fComposite.setLayout(layout); - fComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - } - - /** - * Creates tree viewer control. - * @param treeStyle Tree style. - */ - private void createTreeeViewer(int treeStyle) { - fTreeViewer = new ProblemTreeViewer(fComposite, treeStyle); - final Tree tree = fTreeViewer.getTree(); - tree.setLayoutData(new GridData(GridData.FILL_BOTH)); - fTreeContentProvider = new CContentOutlinerProvider(fTreeViewer); - fSorter = new OutlineSorter(); - fTreeViewer.setContentProvider(fTreeContentProvider); - if (getSettings().getBoolean(STORE_SORT_ENABLED)) { - fTreeViewer.setSorter(fSorter); - } - fTreeViewer.setLabelProvider(new DecoratingCLabelProvider( - new StandardCElementLabelProvider(TEXT_FLAGS, IMAGE_FLAGS), true)); - fTreeViewer.setAutoExpandLevel(AbstractTreeViewer.ALL_LEVELS); - tree.addKeyListener(createKeyListenerForTreeViewer()); - tree.addSelectionListener(createSelectionListenerForTreeViewer()); - tree.addMouseMoveListener(createMouseMoveListenerForTreeViewer()); - tree.addMouseListener(createMouseListenerForTreeViewer(tree)); - } - - /** - * Creates horizontal separator between filter text and outline. - */ - private void createHorizontalSeparator() { - Label separator = new Label(fComposite, SWT.SEPARATOR | SWT.HORIZONTAL - | SWT.LINE_DOT); - separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - } - - /** - * Creates toolbar. - */ - private void createToolbar() { - fToolbarComposite = new Composite(fComposite, SWT.NONE); - final GridLayout layout = new GridLayout(2, false); - layout.marginHeight = 0; - layout.marginWidth = 0; - fToolbarComposite.setLayout(layout); - fToolbarComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - createFilterText(); - createViewMenu(); - } - - /** - * Creates control for filter text. - */ - private void createFilterText() { - fFilterText = new Text(fToolbarComposite, SWT.NONE); - final GridData data = new GridData(GridData.FILL_HORIZONTAL); - final GC gc = new GC(fComposite); - gc.setFont(fComposite.getFont()); - final FontMetrics fontMetrics = gc.getFontMetrics(); - gc.dispose(); - - data.heightHint = Dialog.convertHeightInCharsToPixels(fontMetrics, 1); - data.horizontalAlignment = GridData.FILL; - data.verticalAlignment = GridData.CENTER; - fFilterText.setLayoutData(data); - - fFilterText.addKeyListener(createKeyListenerForFilterContol()); - fFilterText.addModifyListener(createModifyListenerForFilterControl()); - } - - /** - * Creates view menu for toolbar. In this menu options will be displayed. - */ - private void createViewMenu() { - fToolBar= new ToolBar(fToolbarComposite, SWT.FLAT); - final ToolItem viewMenuButton= new ToolItem(fToolBar, SWT.PUSH, 0); - - final GridData data= new GridData(); - data.horizontalAlignment= GridData.END; - data.verticalAlignment= GridData.BEGINNING; - fToolBar.setLayoutData(data); - - viewMenuButton.setImage(CPluginImages.get(CPluginImages.IMG_VIEW_MENU)); - createSelectionListenerForOptions(viewMenuButton); - } - - /** - * Creates selection listener for options. - * @param viewMenuButton Button to create selection adapter. - */ - private void createSelectionListenerForOptions(ToolItem viewMenuButton) { - viewMenuButton.addSelectionListener(new SelectionAdapter() { - /** - * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) - */ - public void widgetSelected(SelectionEvent e) { - fIsDeactivationActive = false; - - final Menu menu = getViewMenuManager().createContextMenu(fShell); - final Rectangle bounds = fToolBar.getBounds(); - final Point topLeft = fShell.toDisplay(new Point(bounds.x, bounds.y + bounds.height)); - menu.setLocation(topLeft.x, topLeft.y); - - menu.setVisible(true); - } - }); - } - - /** - * Creates mouse listener for tree viewer. - * - * @return Created mouse listener. - */ - private MouseListener createMouseListenerForTreeViewer(final Tree tree) { - final MouseListener mouseListener = new MouseAdapter() { - public void mouseUp(MouseEvent e) { - - if (tree.getSelectionCount() < 1) - return; - - if (e.button != 1) - return; - - if (tree.equals(e.getSource())) { - Object o= tree.getItem(new Point(e.x, e.y)); - TreeItem selection= tree.getSelection()[0]; - if (selection.equals(o)) - gotoSelectedElement(); - } - } - }; - return mouseListener; - } - - /** - * Creates mouse move listener for tree viewer. - * - * @return Mouse move listener. - */ - private MouseMoveListener createMouseMoveListenerForTreeViewer() { - // Copied from AbstractInformationControl. - final MouseMoveListener moveListener = new MouseMoveListener() { - TreeItem fLastItem = null; - - public void mouseMove(MouseEvent e) { - final Tree tree = fTreeViewer.getTree(); - if (tree.equals(e.getSource())) { - Object o = tree.getItem(new Point(e.x, e.y)); - if (o instanceof TreeItem) { - if (!o.equals(fLastItem)) { - fLastItem = (TreeItem) o; - tree.setSelection(new TreeItem[] { fLastItem }); - } else if (e.y < tree.getItemHeight() / 4) { - // Scroll up - Point p = tree.toDisplay(e.x, e.y); - Item item = fTreeViewer.scrollUp(p.x, p.y); - if (item instanceof TreeItem) { - fLastItem = (TreeItem) item; - tree.setSelection(new TreeItem[] { fLastItem }); - } - } else if (e.y > tree.getBounds().height - - tree.getItemHeight() / 4) { - // Scroll down - Point p = tree.toDisplay(e.x, e.y); - Item item = fTreeViewer.scrollDown(p.x, p.y); - if (item instanceof TreeItem) { - fLastItem = (TreeItem) item; - tree.setSelection(new TreeItem[] { fLastItem }); - } - } - } - } - } - }; - return moveListener; - } - - /** - * Creates selection listener for tree viewer. - * - * @return Created selection listener. - */ - private SelectionListener createSelectionListenerForTreeViewer() { - final SelectionListener selectionListener = new SelectionListener() { - /** - * @see org.eclipse.swt.events.SelectionListener#widgetSelected(org.eclipse.swt.events.SelectionEvent) - */ - public void widgetSelected(SelectionEvent e) { - // Does not need implementation. - } - - /** - * @see org.eclipse.swt.events.SelectionListener#widgetDefaultSelected(org.eclipse.swt.events.SelectionEvent) - */ - public void widgetDefaultSelected(SelectionEvent e) { - gotoSelectedElement(); - } - }; - return selectionListener; - } - - /** - * Creates key listener for tree viewer. - * - * @return Created listener. - */ - private KeyListener createKeyListenerForTreeViewer() { - final KeyListener listener = new KeyListener() { - /** - * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent) - */ - public void keyPressed(KeyEvent e) { - if (e.keyCode == 0x1B) // ESC - { - dispose(); - } - } - - /** - * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent) - */ - public void keyReleased(KeyEvent e) { - // Does not need implementation. - } - }; - return listener; - } - - /** - * Creates modify listener for filter text control. - * - * @return Modify listener. - */ - private ModifyListener createModifyListenerForFilterControl() { - final ModifyListener modifyListener = new ModifyListener() { - public void modifyText(ModifyEvent e) { - String text = ((Text) e.widget).getText(); - final int length = text.length(); - if (length > 0 && text.charAt(length - 1) != '*') { - text = text + '*'; - } - ((CContentOutlinerProvider) fTreeContentProvider).updateFilter(text); - } - }; - return modifyListener; - } - - /** - * Creates key listener for filter text control. - * - * @return Key listener. - */ - private KeyListener createKeyListenerForFilterContol() { - final KeyListener keyListener = new KeyListener() { - /** - * @see org.eclipse.swt.events.KeyListener#keyPressed(org.eclipse.swt.events.KeyEvent) - */ - public void keyPressed(KeyEvent e) { - if (e.keyCode == 0x0D) { - // Should select entered element. - } - if (e.keyCode == SWT.ARROW_DOWN) { - fTreeViewer.getTree().setFocus(); - } - if (e.keyCode == SWT.ARROW_UP) { - fTreeViewer.getTree().setFocus(); - } - if (e.character == 0x1B) // ESC - { - dispose(); - } - } - - /** - * @see org.eclipse.swt.events.KeyListener#keyReleased(org.eclipse.swt.events.KeyEvent) - */ - public void keyReleased(KeyEvent e) { - // Does not need implementation. - } - }; - return keyListener; - } - - /** - * Creates control listener for shell. - */ - private void createControlListener() { - // Copied from AbstractInformationControl. - fControlListener = new ControlAdapter() { - /** - * @see org.eclipse.swt.events.ControlListener#controlMoved(org.eclipse.swt.events.ControlEvent) - */ - public void controlMoved(ControlEvent e) { - fBounds = fShell.getBounds(); - if (fTrim != null) { - final Point location = fComposite.getLocation(); - fBounds.x = fBounds.x - fTrim.x + location.x; - fBounds.y = fBounds.y - fTrim.y + location.y; - } - - } - - /** - * @see org.eclipse.swt.events.ControlListener#controlResized(org.eclipse.swt.events.ControlEvent) - */ - public void controlResized(ControlEvent e) { - fBounds = fShell.getBounds(); - if (fTrim != null) { - final Point location = fComposite.getLocation(); - fBounds.x = fBounds.x - fTrim.x + location.x; - fBounds.y = fBounds.y - fTrim.y + location.y; - } - } - }; - } - - /** - * Creates deactivation listener. It closes the control is shell becomes - * active. - */ - private void createDeactivationListener() { - fDeactivateListener = new Listener() { - /** - * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event) - */ - public void handleEvent(Event event) { - if (fIsDeactivationActive) { - dispose(); - } - } - }; - } - - /** - * Creates shell listener for management deactivation state. - */ - private void createShellListener() { - fShellListener = new ShellAdapter() { - /** - * @see org.eclipse.swt.events.ShellListener#shellActivated(org.eclipse.swt.events.ShellEvent) - */ - public void shellActivated(ShellEvent e) { - if (e.widget == fShell && fShell.getShells().length == 0) { - fIsDeactivationActive = true; - } - } - }; - } - - /** - * Returns setting for this control. - * @return Settings. - */ - IDialogSettings getSettings() { - final String sectionName = "org.eclipse.jdt.internal.ui.text.QuickOutline"; //$NON-NLS-1$ - IDialogSettings settings= CUIPlugin.getDefault().getDialogSettings().getSection(sectionName); - if (settings == null) - { - settings= CUIPlugin.getDefault().getDialogSettings().addNewSection(sectionName); - } - - return settings; - } - - /** - * - * Border fill layout. Copied from AbstractInformationControl. - * - * @author P.Tomaszewski - */ - private static class BorderFillLayout extends Layout { - - /** The border widths. */ - final int fBorderSize; - - /** - * Creates a fill layout with a border. - * - * @param borderSize - * the border size - */ - public BorderFillLayout(int borderSize) { - if (borderSize < 0) - throw new IllegalArgumentException(); - fBorderSize = borderSize; - } - - /** - * Returns the border size. - * - * @return the border size - */ - public int getBorderSize() { - return fBorderSize; - } - - /** - * @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, - * int, int, boolean) - */ - protected Point computeSize(Composite composite, int wHint, int hHint, - boolean flushCache) { - - Control[] children = composite.getChildren(); - Point minSize = new Point(0, 0); - - if (children != null) { - for (int i = 0; i < children.length; i++) { - Point size = children[i].computeSize(wHint, hHint, - flushCache); - minSize.x = Math.max(minSize.x, size.x); - minSize.y = Math.max(minSize.y, size.y); - } - } - - minSize.x += fBorderSize * 2 + RIGHT_MARGIN; - minSize.y += fBorderSize * 2; - - return minSize; - } - - /** - * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean) - */ - protected void layout(Composite composite, boolean flushCache) { - - final Control[] children = composite.getChildren(); - final Point minSize = new Point(composite.getClientArea().width, - composite.getClientArea().height); - - if (children != null) { - for (int i = 0; i < children.length; i++) { - final Control child = children[i]; - child.setSize(minSize.x - fBorderSize * 2, minSize.y - - fBorderSize * 2); - child.setLocation(fBorderSize, fBorderSize); - } - } - } - } - - /** - * A-Z Sorter for outline. - * - * @author P.Tomaszewski - */ - private class OutlineSorter extends ViewerSorter { - /** - * @see org.eclipse.jface.viewers.ViewerSorter#sort(org.eclipse.jface.viewers.Viewer, - * java.lang.Object[]) - */ - public void sort(Viewer viewer, Object[] elements) { - if (fSort) { - super.sort(viewer, elements); - } - } - - /** - * @see org.eclipse.jface.viewers.ViewerSorter#compare(org.eclipse.jface.viewers.Viewer, - * java.lang.Object, java.lang.Object) - */ - public int compare(Viewer viewer, Object e1, Object e2) { - int result = 0; - if (e1 instanceof CElementGrouping && e2 instanceof CElement) { - result = -1; - } else if (e1 instanceof CElement && e2 instanceof CElementGrouping) { - result = 1; - } else { - int elType1; - int elType2; - String elName1; - String elName2; - if (e1 instanceof CElement && e2 instanceof CElement) { - CElement cel1 = (CElement) e1; - CElement cel2 = (CElement) e2; - elType1 = cel1.getElementType(); - elType2 = cel2.getElementType(); - elName1 = cel1.getElementName(); - elName2 = cel2.getElementName(); - - } else { - CElementGrouping cel1 = (CElementGrouping) e1; - CElementGrouping cel2 = (CElementGrouping) e2; - elType1 = cel1.getType(); - elType2 = cel2.getType(); - elName1 = cel1.toString(); - elName2 = cel2.toString(); - } - if (elType1 == elType2) { - result = elName1.compareTo(elName2); - } else { - if (elType1 > elType2) { - result = -1; - } else if (elType1 < elType2) { - result = 1; - } else { - result = 0; - } - } - } - return result; - } - } - - /** - * The view menu's Remember Size and Location action. - */ - private class RememberBoundsAction extends Action { - - /** - * Creates new action. - */ - RememberBoundsAction() { - super(ActionMessages.getString("COutlineInformationControl.viewMenu.remember.label"), IAction.AS_CHECK_BOX); //$NON-NLS-1$ - setChecked(getSettings().getBoolean(STORE_RESTORE_LOCATION)); - } - - /** - * @see org.eclipse.jface.action.Action#run() - */ - public void run() { - final IDialogSettings settings = getSettings(); - - final boolean newValue = isChecked(); - - // store new value - settings.put(STORE_RESTORE_LOCATION, newValue); - settings.put(STORE_RESTORE_SIZE, newValue); - - fIsDeactivationActive = true; - } - } - - /** - * - * The view menu's Move action. - * - * @author P.Tomaszewski - */ - private class MoveAction extends Action { - - /** - * Creates new action. - */ - MoveAction() { - super(ActionMessages.getString("COutlineInformationControl.viewMenu.move.label"), IAction.AS_PUSH_BUTTON); //$NON-NLS-1$ - } - - /** - * @see org.eclipse.jface.action.Action#run() - */ - public void run() { - final Tracker tracker= new Tracker(fShell.getDisplay(), SWT.NONE); - tracker.setStippled(true); - final Rectangle[] r= new Rectangle[] { fFilterText.getShell().getBounds() }; - tracker.setRectangles(r); - if (tracker.open()) { - fShell.setBounds(tracker.getRectangles()[0]); - } - } - } - /** * * The view menu's Sort action. * * @author P.Tomaszewski */ - private class SortAction extends Action { + private class LexicalSortingAction extends Action { - /** - * Creates new action. - */ - SortAction() { - super(ActionMessages.getString("COutlineInformationControl.viewMenu.sort.label"), IAction.AS_CHECK_BOX); //$NON-NLS-1$ - setChecked(getSettings().getBoolean(STORE_SORT_ENABLED)); - } + private static final String STORE_LEXICAL_SORTING_CHECKED= "LexicalSortingAction.isChecked"; //$NON-NLS-1$ - /** - * @see org.eclipse.jface.action.Action#run() - */ - public void run() { - final boolean newValue = isChecked(); - if (newValue) { - fTreeViewer.setSorter(fSorter); - } else { - fTreeViewer.setSorter(null); - } - getSettings().put(STORE_SORT_ENABLED, newValue); - fIsDeactivationActive = true; - } + /** The tree viewer */ + private TreeViewer fOutlineViewer; + /** Sorter for tree viewer. */ + private LexicalCSorter fSorter; + + /** + * Creates new action. + */ + public LexicalSortingAction(TreeViewer treeViewer) { + super(ActionMessages.getString("COutlineInformationControl.viewMenu.sort.label"), IAction.AS_CHECK_BOX); //$NON-NLS-1$ + CPluginImages.setLocalImageDescriptors(this, CPluginImages.IMG_ALPHA_SORTING); + PlatformUI.getWorkbench().getHelpSystem().setHelp(this, ICHelpContextIds.LEXICAL_SORTING_BROWSING_ACTION); + + fOutlineViewer= treeViewer; + fSorter= new LexicalCSorter(); + + boolean checked= getDialogSettings().getBoolean(STORE_LEXICAL_SORTING_CHECKED); + setChecked(checked); + + if (checked && fOutlineViewer != null) { + fOutlineViewer.setComparator(fSorter); + } + } + + /* + * @see org.eclipse.jface.action.Action#run() + */ + public void run() { + final boolean on= isChecked(); + fOutlineViewer.setComparator(on ? fSorter : null); + getDialogSettings().put(STORE_LEXICAL_SORTING_CHECKED, on); + } } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java index 26c34be094d..2151f1e94e8 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CSourceViewerConfiguration.java @@ -19,8 +19,8 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.content.IContentType; -import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.text.AbstractInformationControlManager; import org.eclipse.jface.text.DefaultInformationControl; import org.eclipse.jface.text.IAutoEditStrategy; import org.eclipse.jface.text.IDocument; @@ -240,18 +240,18 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { * @return Presenter with outline view. */ public IInformationPresenter getOutlinePresenter(ISourceViewer sourceViewer) { - final IInformationControlCreator outlineControlCreator = getOutlineContolCreator(); + final IInformationControlCreator outlineControlCreator = getOutlineControlCreator(); final InformationPresenter presenter = new InformationPresenter(outlineControlCreator); presenter.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer)); - final IInformationProvider provider = new CElementContentProvider(getEditor()); + presenter.setAnchor(AbstractInformationControlManager.ANCHOR_GLOBAL); + final IInformationProvider provider = new CElementContentProvider(getEditor()); presenter.setInformationProvider(provider, IDocument.DEFAULT_CONTENT_TYPE); presenter.setInformationProvider(provider, ICPartitions.C_MULTI_LINE_COMMENT); presenter.setInformationProvider(provider, ICPartitions.C_SINGLE_LINE_COMMENT); presenter.setInformationProvider(provider, ICPartitions.C_STRING); presenter.setInformationProvider(provider, ICPartitions.C_CHARACTER); presenter.setInformationProvider(provider, ICPartitions.C_PREPROCESSOR); - presenter.setSizeConstraints(20, 20, true, false); - presenter.setRestoreInformationControlBounds(getSettings("outline_presenter_bounds"), true, true); //$NON-NLS-1$ + presenter.setSizeConstraints(50, 20, true, false); return presenter; } @@ -686,7 +686,7 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { * Creates control for outline presentation in editor. * @return Control. */ - private IInformationControlCreator getOutlineContolCreator() { + private IInformationControlCreator getOutlineControlCreator() { final IInformationControlCreator conrolCreator = new IInformationControlCreator() { /** * @see org.eclipse.jface.text.IInformationControlCreator#createInformationControl(org.eclipse.swt.widgets.Shell) @@ -699,21 +699,6 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration { }; return conrolCreator; } - - /** - * Returns the settings for the given section. - * - * @param sectionName the section name - * @return the settings - */ - private IDialogSettings getSettings(String sectionName) { - IDialogSettings settings= CUIPlugin.getDefault().getDialogSettings().getSection(sectionName); - if (settings == null) { - settings= CUIPlugin.getDefault().getDialogSettings().addNewSection(sectionName); - } - - return settings; - } protected ILanguage getLanguage() { if (fTextEditor == null) {