]> git.uio.no Git - ifi-stolz-refaktor.git/blobdiff - case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/javaeditor/breadcrumb/EditorBreadcrumb.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / internal / ui / javaeditor / breadcrumb / EditorBreadcrumb.java
diff --git a/case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/javaeditor/breadcrumb/EditorBreadcrumb.java b/case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/javaeditor/breadcrumb/EditorBreadcrumb.java
new file mode 100644 (file)
index 0000000..ece918e
--- /dev/null
@@ -0,0 +1,528 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 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.jdt.internal.ui.javaeditor.breadcrumb;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MenuDetectEvent;
+import org.eclipse.swt.events.MenuDetectListener;
+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.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Widget;
+
+import org.eclipse.core.runtime.Assert;
+
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.util.IPropertyChangeListener;
+import org.eclipse.jface.util.PropertyChangeEvent;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IOpenListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.OpenEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+
+import org.eclipse.jface.text.ITextViewer;
+
+import org.eclipse.ui.IPartListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.actions.ActionContext;
+import org.eclipse.ui.actions.ActionGroup;
+
+import org.eclipse.ui.texteditor.ITextEditor;
+
+
+/**
+ * The editor breadcrumb shows the parent chain of the active editor item inside a
+ * {@link BreadcrumbViewer}.
+ *
+ * <p>
+ * Clients must implement the abstract methods.
+ * </p>
+ *
+ * @since 3.4
+ */
+public abstract class EditorBreadcrumb implements IBreadcrumb {
+
+       private static final String ACTIVE_TAB_BG_END= "org.eclipse.ui.workbench.ACTIVE_TAB_BG_END"; //$NON-NLS-1$
+
+       private ITextEditor fTextEditor;
+       private ITextViewer fTextViewer;
+
+       private BreadcrumbViewer fBreadcrumbViewer;
+
+       private boolean fHasFocus;
+       private boolean fIsActive;
+
+       private Composite fComposite;
+
+       private Listener fDisplayFocusListener;
+       private Listener fDisplayKeyListener;
+
+       private IPropertyChangeListener fPropertyChangeListener;
+
+       private ISelection fOldTextSelection;
+
+       private IPartListener fPartListener;
+
+
+       /**
+        * The editor inside which this breadcrumb is shown.
+        *
+        * @param editor the editor
+        */
+       public EditorBreadcrumb(ITextEditor editor) {
+               setTextEditor(editor);
+       }
+
+       /**
+        * The active element of the editor.
+        *
+        * @return the active element of the editor, or <b>null</b> if none
+        */
+       protected abstract Object getCurrentInput();
+
+       /**
+        * Create and configure the viewer used to display the parent chain.
+        *
+        * @param parent the parent composite
+        * @return the viewer
+        */
+       protected abstract BreadcrumbViewer createViewer(Composite parent);
+
+       /**
+        * Reveal the given element in the editor if possible.
+        *
+        * @param element the element to reveal
+        * @return true if the element could be revealed
+        */
+       protected abstract boolean reveal(Object element);
+
+       /**
+        * Open the element in a new editor if possible.
+        *
+        * @param element the element to open
+        * @return true if the element could be opened
+        */
+       protected abstract boolean open(Object element);
+
+       /**
+        * Create an action group for the context menu shown for the selection of the given selection
+        * provider or <code>null</code> if no context menu should be shown.
+        *
+        * @param selectionProvider the provider of the context selection
+        * @return action group to use to fill the context menu or <code>null</code>
+        */
+       protected abstract ActionGroup createContextMenuActionGroup(ISelectionProvider selectionProvider);
+
+       /**
+        * The breadcrumb has been activated. Implementors must retarget the editor actions to the
+        * breadcrumb aware actions.
+        */
+       protected abstract void activateBreadcrumb();
+
+       /**
+        * The breadcrumb has been deactivated. Implementors must retarget the breadcrumb actions to the
+        * editor actions.
+        */
+       protected abstract void deactivateBreadcrumb();
+
+       public ISelectionProvider getSelectionProvider() {
+               return fBreadcrumbViewer;
+       }
+
+       protected void setTextViewer(ITextViewer viewer) {
+               fTextViewer= viewer;
+       }
+
+       /*
+        * @see org.eclipse.jdt.internal.ui.javaeditor.IBreadcrumb#setInput(java.lang.Object)
+        */
+       public void setInput(Object element) {
+               if (element == null)
+                       return;
+
+               Object input= fBreadcrumbViewer.getInput();
+               if (input == element || element.equals(input))
+                       return;
+
+               if (fBreadcrumbViewer.isDropDownOpen())
+                       return;
+
+               fBreadcrumbViewer.setInput(element);
+       }
+
+       /*
+        * @see org.eclipse.jdt.internal.ui.javaeditor.IBreadcrumb#setFocus()
+        */
+       public void activate() {
+               if (fBreadcrumbViewer.getSelection().isEmpty())
+                       fBreadcrumbViewer.setSelection(new StructuredSelection(fBreadcrumbViewer.getInput()));
+               fBreadcrumbViewer.setFocus();
+       }
+
+       /*
+        * @see org.eclipse.jdt.internal.ui.javaeditor.breadcrumb.IBreadcrumb#isActive()
+        */
+       public boolean isActive() {
+               return fIsActive;
+       }
+
+       /*
+        * @see org.eclipse.jdt.internal.ui.javaeditor.IBreadcrumb#createContent(org.eclipse.swt.widgets.Composite)
+        */
+       public Control createContent(Composite parent) {
+               Assert.isTrue(fComposite == null, "Content must only be created once."); //$NON-NLS-1$
+
+               boolean rtl= (getTextEditor().getSite().getShell().getStyle() & SWT.RIGHT_TO_LEFT) != 0;
+
+               fComposite= new Composite(parent, rtl ? SWT.RIGHT_TO_LEFT : SWT.NONE);
+               GridData data= new GridData(SWT.FILL, SWT.TOP, true, false);
+               fComposite.setLayoutData(data);
+               GridLayout gridLayout= new GridLayout(1, false);
+               gridLayout.marginWidth= 0;
+               gridLayout.marginHeight= 0;
+               gridLayout.verticalSpacing= 0;
+               gridLayout.horizontalSpacing= 0;
+               fComposite.setLayout(gridLayout);
+
+               fDisplayFocusListener= new Listener() {
+                       public void handleEvent(Event event) {
+                               if (isBreadcrumbEvent(event)) {
+                                       if (fHasFocus)
+                                               return;
+
+                                       fIsActive= true;
+
+                                       focusGained();
+                               } else {
+                                       if (!fIsActive)
+                                               return;
+
+                                       boolean hasTextFocus= fTextViewer.getTextWidget().isFocusControl();
+                                       if (hasTextFocus) {
+                                               fIsActive= false;
+                                       }
+
+                                       if (!fHasFocus)
+                                               return;
+
+                                       focusLost();
+                               }
+                       }
+               };
+               Display.getCurrent().addFilter(SWT.FocusIn, fDisplayFocusListener);
+
+               fBreadcrumbViewer= createViewer(fComposite);
+               fBreadcrumbViewer.getControl().setBackground(Display.getDefault().getSystemColor(SWT.COLOR_WHITE));
+
+               fBreadcrumbViewer.addDoubleClickListener(new IDoubleClickListener() {
+                       public void doubleClick(DoubleClickEvent event) {
+                               Object element= ((IStructuredSelection) event.getSelection()).getFirstElement();
+                               if (element == null)
+                                       return;
+
+                               BreadcrumbItem item= (BreadcrumbItem) fBreadcrumbViewer.doFindItem(element);
+                               if (item == null)
+                                       return;
+
+                               int index= fBreadcrumbViewer.getIndexOfItem(item);
+                               BreadcrumbItem parentItem= fBreadcrumbViewer.getItem(index - 1);
+                               parentItem.openDropDownMenu();
+                       }
+               });
+
+               fBreadcrumbViewer.addOpenListener(new IOpenListener() {
+                       public void open(OpenEvent event) {
+                               doRevealOrOpen(event.getSelection());
+                       }
+               });
+
+               fBreadcrumbViewer.addMenuDetectListener(new MenuDetectListener() {
+                       public void menuDetected(MenuDetectEvent event) {
+                               ISelectionProvider selectionProvider;
+                               if (fBreadcrumbViewer.isDropDownOpen()) {
+                                       selectionProvider= fBreadcrumbViewer.getDropDownSelectionProvider();
+                               } else {
+                                       selectionProvider= fBreadcrumbViewer;
+                               }
+
+                               ActionGroup actionGroup= createContextMenuActionGroup(selectionProvider);
+                               if (actionGroup == null)
+                                       return;
+
+                               try {
+                                       MenuManager manager= new MenuManager();
+                                       actionGroup.setContext(new ActionContext(selectionProvider.getSelection()));
+                                       actionGroup.fillContextMenu(manager);
+
+                                       getTextEditor().getEditorSite().registerContextMenu(manager, selectionProvider, false);
+
+                                       if (manager.isEmpty())
+                                               return;
+
+                                       Menu menu= manager.createContextMenu(fBreadcrumbViewer.getControl());
+                                       menu.setLocation(event.x + 10, event.y + 10);
+                                       menu.setVisible(true);
+                                       while (!menu.isDisposed() && menu.isVisible()) {
+                                               if (!menu.getDisplay().readAndDispatch())
+                                                       menu.getDisplay().sleep();
+                                       }
+                               } finally {
+                                       actionGroup.dispose();
+                               }
+                       }
+               });
+
+               fPropertyChangeListener= new IPropertyChangeListener() {
+                       public void propertyChange(PropertyChangeEvent event) {
+                               if (ACTIVE_TAB_BG_END.equals(event.getProperty())) {
+                                       if (fComposite.isFocusControl()) {
+                                               fComposite.setBackground(JFaceResources.getColorRegistry().get(ACTIVE_TAB_BG_END));
+                                       }
+                               }
+                       }
+               };
+               JFaceResources.getColorRegistry().addListener(fPropertyChangeListener);
+
+               return fComposite;
+       }
+
+       /*
+        * @see org.eclipse.jdt.internal.ui.javaeditor.IEditorViewPart#dispose()
+        */
+       public void dispose() {
+               if (fPropertyChangeListener != null) {
+                       JFaceResources.getColorRegistry().removeListener(fPropertyChangeListener);
+               }
+               if (fDisplayFocusListener != null) {
+                       Display.getDefault().removeFilter(SWT.FocusIn, fDisplayFocusListener);
+               }
+               deinstallDisplayListeners();
+               if (fPartListener != null) {
+                       getTextEditor().getSite().getPage().removePartListener(fPartListener);
+               }
+
+               setTextEditor(null);
+       }
+
+       /**
+        * Either reveal the selection in the editor or open the selection in a new editor. If both fail
+        * open the child pop up of the selected element.
+        *
+        * @param selection the selection to open
+        */
+       private void doRevealOrOpen(ISelection selection) {
+               if (doReveal(selection)) {
+                       fTextViewer.getTextWidget().setFocus();
+               } else if (doOpen(selection)) {
+                       fIsActive= false;
+                       focusLost();
+                       fBreadcrumbViewer.setInput(getCurrentInput());
+               }
+       }
+
+       private boolean doOpen(ISelection selection) {
+               if (!(selection instanceof StructuredSelection))
+                       return false;
+
+               StructuredSelection structuredSelection= (StructuredSelection) selection;
+               if (structuredSelection.isEmpty())
+                       return false;
+
+               return open(structuredSelection.getFirstElement());
+       }
+
+       private boolean doReveal(ISelection selection) {
+               if (!(selection instanceof StructuredSelection))
+                       return false;
+
+               StructuredSelection structuredSelection= (StructuredSelection) selection;
+               if (structuredSelection.isEmpty())
+                       return false;
+
+               if (fOldTextSelection != null) {
+                       getTextEditor().getSelectionProvider().setSelection(fOldTextSelection);
+
+                       boolean result= reveal(structuredSelection.getFirstElement());
+
+                       fOldTextSelection= getTextEditor().getSelectionProvider().getSelection();
+                       getTextEditor().getSelectionProvider().setSelection(new StructuredSelection(this));
+                       return result;
+               } else {
+                       return reveal(structuredSelection.getFirstElement());
+               }
+       }
+
+       /**
+        * Focus has been transfered into the breadcrumb.
+        */
+       private void focusGained() {
+               if (fHasFocus)
+                       focusLost();
+
+               fComposite.setBackground(JFaceResources.getColorRegistry().get(ACTIVE_TAB_BG_END));
+               fHasFocus= true;
+
+               installDisplayListeners();
+
+               activateBreadcrumb();
+
+               getTextEditor().getEditorSite().getActionBars().updateActionBars();
+
+               fOldTextSelection= getTextEditor().getSelectionProvider().getSelection();
+
+               getTextEditor().getSelectionProvider().setSelection(new StructuredSelection(this));
+       }
+
+       /**
+        * Focus has been revoked from the breadcrumb.
+        */
+       private void focusLost() {
+               if (!fHasFocus)
+                       return;
+
+               fComposite.setBackground(null);
+               fHasFocus= false;
+
+               deinstallDisplayListeners();
+
+               deactivateBreadcrumb();
+
+               getTextEditor().getEditorSite().getActionBars().updateActionBars();
+
+               getTextEditor().getSelectionProvider().setSelection(fOldTextSelection);
+               fOldTextSelection= null;
+       }
+
+       /**
+        * Installs all display listeners.
+        */
+       private void installDisplayListeners() {
+               //Sanity check
+               deinstallDisplayListeners();
+
+               fDisplayKeyListener= new Listener() {
+                       public void handleEvent(Event event) {
+                               if (event.keyCode != SWT.ESC)
+                                       return;
+
+                               if (!isBreadcrumbEvent(event))
+                                       return;
+
+                               fTextViewer.getTextWidget().setFocus();
+                       }
+               };
+               Display.getDefault().addFilter(SWT.KeyDown, fDisplayKeyListener);
+       }
+
+       /**
+        * Removes all previously installed display listeners.
+        */
+       private void deinstallDisplayListeners() {
+               if (fDisplayKeyListener != null) {
+                       Display.getDefault().removeFilter(SWT.KeyDown, fDisplayKeyListener);
+                       fDisplayKeyListener= null;
+               }
+       }
+
+       /**
+        * Tells whether the given event was issued inside the breadcrumb viewer's control.
+        *
+        * @param event the event to inspect
+        * @return <code>true</code> if event was generated by a breadcrumb child
+        */
+       private boolean isBreadcrumbEvent(Event event) {
+               if (fBreadcrumbViewer == null)
+                       return false;
+
+               Widget item= event.widget;
+               if (!(item instanceof Control))
+                       return false;
+
+               Shell dropDownShell= fBreadcrumbViewer.getDropDownShell();
+               if (dropDownShell != null && isChild((Control) item, dropDownShell))
+                       return true;
+
+               return isChild((Control) item, fBreadcrumbViewer.getControl());
+       }
+
+       private boolean isChild(Control child, Control parent) {
+               if (child == null)
+                       return false;
+
+               if (child == parent)
+                       return true;
+
+               return isChild(child.getParent(), parent);
+       }
+
+       /**
+        * Sets the text editor for which this breadcrumb is.
+        *
+        * @param textEditor the text editor to be used
+        */
+       protected void setTextEditor(ITextEditor textEditor) {
+               fTextEditor= textEditor;
+
+               if (fTextEditor == null)
+                       return;
+
+               fPartListener= new IPartListener() {
+
+                       public void partActivated(IWorkbenchPart part) {
+                               if (part == fTextEditor && fHasFocus) {
+                                       //focus-in event comes before part activation and the
+                                       //workbench activates the editor -> reactivate the breadcrumb
+                                       //if it is the active part.
+                                       focusGained();
+                               }
+                       }
+
+                       public void partBroughtToTop(IWorkbenchPart part) {
+                       }
+
+                       public void partClosed(IWorkbenchPart part) {
+
+                       }
+
+                       public void partDeactivated(IWorkbenchPart part) {
+                               if (part == fTextEditor && fHasFocus) {
+                                       focusLost();
+                               }
+                       }
+
+                       public void partOpened(IWorkbenchPart part) {
+                       }
+
+               };
+               fTextEditor.getSite().getPage().addPartListener(fPartListener);
+       }
+
+       /**
+        * This breadcrumb's text editor.
+        *
+        * @return the text editor
+        */
+       protected ITextEditor getTextEditor() {
+               return fTextEditor;
+       }
+
+}