Java tutorial
/*=============================================================================# # Copyright (c) 2010-2015 Stephan Wahlbrink (WalWare.de) 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: # Stephan Wahlbrink - initial API and implementation #=============================================================================*/ package de.walware.ecommons.ui.breadcrumb; 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.swt.SWT; 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.Shell; import org.eclipse.swt.widgets.Widget; import org.eclipse.ui.contexts.IContextService; import org.eclipse.ui.internal.services.IServiceLocatorCreator; import org.eclipse.ui.internal.services.ServiceLocator; import org.eclipse.ui.services.IDisposable; import org.eclipse.ui.services.IServiceLocator; import de.walware.ecommons.ui.util.LayoutUtil; public abstract class AbstractBreadcrumb implements IBreadcrumb { private static final String ACTIVE_TAB_BG_END = "org.eclipse.ui.workbench.ACTIVE_TAB_BG_END"; //$NON-NLS-1$ private BreadcrumbViewer fBreadcrumbViewer; private boolean fHasFocus; private boolean fIsActive; private Composite fComposite; private Listener fDisplayFocusListener; private Listener fDisplayKeyListener; private IPropertyChangeListener fPropertyChangeListener; private int fBreadcrumbServiceState; private ServiceLocator fBreadcrumbServices; public AbstractBreadcrumb() { } @Override public ISelectionProvider getSelectionProvider() { return fBreadcrumbViewer; } @Override public void setInput(final Object element) { if (element == null) { return; } final Object input = fBreadcrumbViewer.getInput(); if (element.equals(input)) { return; } if (fBreadcrumbViewer.isDropDownOpen()) { return; } fBreadcrumbViewer.setInput(element); } @Override public void activate() { fBreadcrumbViewer.setSelection(new StructuredSelection(fBreadcrumbViewer.getInput())); fBreadcrumbViewer.setFocus(); } @Override public boolean isActive() { return fIsActive; } @Override public Control createContent(final Composite parent) { assert (fComposite == null); fComposite = new Composite(parent, SWT.NONE); final GridLayout gridLayout = LayoutUtil.applySashDefaults(new GridLayout(), 1); fComposite.setLayout(gridLayout); fDisplayFocusListener = new Listener() { @Override public void handleEvent(final Event event) { if (isBreadcrumbEvent(event)) { if (fHasFocus) { return; } fIsActive = true; focusGained(); } else { if (!fIsActive) { return; } if (hasInputFocus()) { 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.addOpenListener(new IOpenListener() { @Override public void open(final OpenEvent event) { doRevealOrOpen(event.getSelection()); } }); fBreadcrumbViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick(final DoubleClickEvent event) { final Object element = ((IStructuredSelection) event.getSelection()).getFirstElement(); if (element == null) { return; } if (doRevealOrOpen(event.getSelection())) { return; } // final BreadcrumbItem item = (BreadcrumbItem) fBreadcrumbViewer.doFindItem(element); // if (item == null) { // return; // } // final int index = fBreadcrumbViewer.getIndexOfItem(item); // final BreadcrumbItem parentItem = fBreadcrumbViewer.getItem(index - 1); // parentItem.openDropDownMenu(); } }); // fBreadcrumbViewer.addMenuDetectListener(new MenuDetectListener() { // public void menuDetected(final MenuDetectEvent event) { // final ISelectionProvider selectionProvider = (fBreadcrumbViewer.isDropDownOpen()) ? // fBreadcrumbViewer.getDropDownSelectionProvider() : fBreadcrumbViewer; // // System.out.println(fBreadcrumbViewer.isDropDownOpen()); // System.out.println(event); // // final MenuManager manager = new MenuManager(); // try { // fillContextMenu(manager, (IStructuredSelection) selectionProvider.getSelection()); // if (manager.isEmpty()) { // return; // } // final 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 { // manager.dispose(); // } // } // }); fPropertyChangeListener = new IPropertyChangeListener() { @Override public void propertyChange(final 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; } // protected void fillContextMenu(final MenuManager manager, final IStructuredSelection selection) { // } @Override public void dispose() { if (isServiceLocatorReady(false)) { fBreadcrumbServiceState = -1; fBreadcrumbServices.dispose(); fBreadcrumbServices = null; } if (fPropertyChangeListener != null) { JFaceResources.getColorRegistry().removeListener(fPropertyChangeListener); } if (fDisplayFocusListener != null) { Display.getDefault().removeFilter(SWT.FocusIn, fDisplayFocusListener); } deinstallDisplayListeners(); } /** * 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 boolean doRevealOrOpen(final ISelection selection) { if (doReveal(selection)) { setFocusToInput(); return true; } else if (doOpen(selection)) { fIsActive = false; focusLost(); updateInput(); return true; } return false; } private boolean doOpen(final ISelection selection) { if (!(selection instanceof StructuredSelection)) { return false; } final StructuredSelection structuredSelection = (StructuredSelection) selection; if (structuredSelection.isEmpty()) { return false; } return open(structuredSelection.getFirstElement()); } private boolean doReveal(final ISelection selection) { if (!(selection instanceof StructuredSelection)) { return false; } final StructuredSelection structuredSelection = (StructuredSelection) selection; if (structuredSelection.isEmpty()) { return false; } 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(); updateActions(); } /** * Focus has been revoked from the breadcrumb. */ private void focusLost() { fComposite.setBackground(null); fHasFocus = false; deinstallDisplayListeners(); deactivateBreadcrumb(); updateActions(); } /** * Installs all display listeners. */ private void installDisplayListeners() { //Sanity check deinstallDisplayListeners(); fDisplayKeyListener = new Listener() { @Override public void handleEvent(final Event event) { if (event.keyCode != SWT.ESC) { return; } if (!isBreadcrumbEvent(event)) { return; } setFocusToInput(); } }; 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(final Event event) { if (fBreadcrumbViewer == null) { return false; } final Widget item = event.widget; if (!(item instanceof Control)) { return false; } final Shell dropDownShell = fBreadcrumbViewer.getDropDownShell(); if (dropDownShell != null && isChild((Control) item, dropDownShell)) { return true; } return isChild((Control) item, fBreadcrumbViewer.getControl()); } private boolean isChild(final Control child, final Control parent) { if (child == null) { return false; } if (child == parent) { return true; } return isChild(child.getParent(), parent); } private boolean isServiceLocatorReady(final boolean init) { if (fBreadcrumbServiceState == 0) { fBreadcrumbServiceState = -1; final IServiceLocator pageServices = getParentServiceLocator(); final IServiceLocatorCreator serviceCreator = (IServiceLocatorCreator) pageServices .getService(IServiceLocatorCreator.class); fBreadcrumbServices = (ServiceLocator) serviceCreator.createServiceLocator(pageServices, null, new IDisposable() { @Override public void dispose() { fBreadcrumbServiceState = -1; fBreadcrumbServices = null; } }); fBreadcrumbServiceState = 1; initActions(fBreadcrumbServices); } return (fBreadcrumbServiceState > 0); } protected void initActions(final IServiceLocator services) { final IContextService contextService = (IContextService) services.getService(IContextService.class); contextService.activateContext("org.eclipse.jdt.ui.breadcrumbEditorScope"); //$NON-NLS-1$ } protected abstract BreadcrumbViewer createViewer(final Composite parent); protected abstract IServiceLocator getParentServiceLocator(); protected abstract boolean hasInputFocus(); protected abstract void setFocusToInput(); /** * Intend to implement. */ protected void updateActions() { } /** * The breadcrumb has been activated. Implementors must retarget the editor actions to the * breadcrumb aware actions. */ protected void activateBreadcrumb() { if (isServiceLocatorReady(true)) { fBreadcrumbServices.activate(); } } /** * The breadcrumb has been deactivated. Implementors must retarget the breadcrumb actions to the * editor actions. */ protected void deactivateBreadcrumb() { if (isServiceLocatorReady(true)) { fBreadcrumbServices.deactivate(); } } /** * Intend to implement. */ protected void updateInput() { } /** * 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); }