/****************************************************************************** * Copyright (C) 2013 Fabio Zadrozny * * 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: * Fabio Zadrozny <fabiofz@gmail.com> - initial API and implementation ******************************************************************************/ package org.python.pydev.shared_ui.quick_outline; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.KeyEvent; import org.eclipse.swt.events.KeyListener; import org.eclipse.swt.events.ShellEvent; import org.eclipse.swt.events.ShellListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.progress.UIJob; import org.python.pydev.shared_core.structure.DataAndImageTreeNode; import org.python.pydev.shared_ui.SharedUiPlugin; import org.python.pydev.shared_ui.dialogs.DialogMemento; import org.python.pydev.shared_ui.dialogs.TreeSelectionDialog; public abstract class BaseQuickOutlineSelectionDialog extends TreeSelectionDialog { /** * Structure without parents. */ protected DataAndImageTreeNode<Object> root; /** * Structure with the parent methods. */ protected DataAndImageTreeNode<Object> rootWithParents; /** * The first line selected (starts at 1) */ protected int startLineIndex = -1; protected DataAndImageTreeNode<Object> initialSelection; /** * Helper to save/restore geometry. */ private final DialogMemento memento; /** * Listener to handle the 2nd ctrl+O */ private KeyListener ctrlOlistener; /** * Should we show the parents or not? */ private boolean showParentHierarchy; /** * Label indicating what are we showing. */ private Label labelCtrlO; protected final UIJob uiJobSetRootWithParentsInput = new UIJob("Set input") { @Override public IStatus runInUIThread(IProgressMonitor monitor) { if (!monitor.isCanceled()) { getTreeViewer().setInput(rootWithParents); } else { //Will be recalculated if asked again! rootWithParents = null; } return Status.OK_STATUS; } }; private final boolean canShowParentHierarchy; protected BaseQuickOutlineSelectionDialog(Shell shell, String pluginId, ILabelProvider labelProvider, ITreeContentProvider contentProvider, boolean canShowParentHierarchy) { super(shell, labelProvider, contentProvider); setShellStyle(getShellStyle() & ~SWT.APPLICATION_MODAL); //Not modal because then the user may cancel the progress. if (SharedUiPlugin.getDefault() != null) { memento = new DialogMemento(getShell(), pluginId + ".actions.QuickShowOutline"); } else { memento = null; } this.canShowParentHierarchy = canShowParentHierarchy; setMessage("Filter (press enter to go to selected element)"); setTitle("Quick Outline"); setAllowMultiple(false); this.showParentHierarchy = false; } protected void toggleShowParentHierarchy() { showParentHierarchy = !showParentHierarchy; updateShowParentHierarchyMessage(); TreeViewer treeViewer = this.getTreeViewer(); if (showParentHierarchy) { //Create the DataAndImageTreeNode structure if it's still not created... calculateHierarchyWithParents(); } else { calculateHierarchy(); treeViewer.setInput(root); } } protected abstract void calculateHierarchy(); protected abstract void calculateHierarchyWithParents(); @Override protected void configureShell(final Shell shell) { super.configureShell(shell); //Whenever the shell is deactivated, we want to go on and close it (i.e.: work as a popup dialog) shell.addShellListener(new ShellListener() { @Override public void shellIconified(ShellEvent e) { } @Override public void shellDeiconified(ShellEvent e) { } @Override public void shellDeactivated(ShellEvent e) { shell.close(); } @Override public void shellClosed(ShellEvent e) { } @Override public void shellActivated(ShellEvent e) { } }); } @Override public Control createDialogArea(Composite parent) { if (memento != null) { memento.readSettings(); } Control ret = super.createDialogArea(parent); if (canShowParentHierarchy) { ctrlOlistener = new KeyListener() { @Override public void keyReleased(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { if ((e.keyCode == 'o' || e.keyCode == 'O') && e.stateMask == SWT.CTRL) { toggleShowParentHierarchy(); } } }; this.text.addKeyListener(ctrlOlistener); } this.text.addKeyListener(new KeyListener() { @Override public void keyReleased(KeyEvent e) { } @Override public void keyPressed(KeyEvent e) { if (e.keyCode == SWT.CR || e.keyCode == SWT.LF || e.keyCode == SWT.KEYPAD_CR) { okPressed(); } } }); if (canShowParentHierarchy) { this.getTreeViewer().getTree().addKeyListener(ctrlOlistener); } return ret; } /* (non-Javadoc) * @see org.eclipse.ui.dialogs.SelectionStatusDialog#createButtonBar(org.eclipse.swt.widgets.Composite) */ @Override protected Control createButtonBar(Composite parent) { if (canShowParentHierarchy) { labelCtrlO = new Label(parent, SWT.NONE); this.labelCtrlO.addKeyListener(ctrlOlistener); updateShowParentHierarchyMessage(); } return labelCtrlO; } protected void updateShowParentHierarchyMessage() { if (canShowParentHierarchy) { if (showParentHierarchy) { labelCtrlO.setText("Press Ctrl+O to hide parent hierarchy."); } else { labelCtrlO.setText("Press Ctrl+O to show parent hierarchy."); } } } @Override public boolean close() { if (memento != null) { memento.writeSettings(getShell()); } return super.close(); } @Override protected Point getInitialSize() { if (memento != null) { return memento.getInitialSize(super.getInitialSize(), getShell()); } return new Point(640, 480); } @Override protected Point getInitialLocation(Point initialSize) { if (memento != null) { return memento.getInitialLocation(initialSize, super.getInitialLocation(initialSize), getShell()); } return new Point(250, 250); } @Override protected int getDefaultMargins() { return 0; } @Override protected int getDefaultSpacing() { return 0; } }