/*******************************************************************************
* Copyright © 2008, 2013 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.edt.ide.ui.internal.outline;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.edt.ide.core.model.document.IEGLDocument;
import org.eclipse.edt.ide.core.model.document.IEGLModelChangeListener;
import org.eclipse.edt.ide.ui.EDTUIPlugin;
import org.eclipse.edt.ide.ui.internal.editor.EGLEditor;
import org.eclipse.edt.ide.ui.internal.util.FileProvidingView;
import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.ListenerList;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.IElementComparer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.operations.RedoActionHandler;
import org.eclipse.ui.operations.UndoActionHandler;
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
public class OutlinePage extends ContentOutlinePage implements IEGLModelChangeListener, IMenuListener, FileProvidingView {
public static final String TOGGLE_PRESENTATION= "togglePresentation"; //$NON-NLS-1$
private static final String[] EGLUIWEBTRANSACTION = new String[] {"egl", "ui", "webTransaction"};
private IEGLDocument document;
private OutlineAdapterFactory factory;
private String fOutlinerContextMenuID;
// private IEditorInput editorInput;
// private EGLOutlineExpandCollapseAction expandAction;
// private EGLOutlineExpandCollapseAction collapseAction;
// private EGLOutlineOpenInPartsRefAction openInPartsRefAction;
// private EGLOutlineGenerateAction generateAction;
// private EGLOutlineGenerateWithWizardAction generateWithWizardAction;
// private EGLOutlineRemoveAction removeAction;
// private EGLOutlineSortAction sortByNameAction;
// private EGLOutlineSortAction sortByTypeAction;
// private EGLOutlineSortAction sortByOrderAction;
// private EGLSQLRetrieveAction retrieveSQLAction;
// private EGLCreateDataItemAction createDataItemAction;
// private EGLOrganizeFormsAction organizeFormsAction;
private IMenuManager submenu;
private TreeViewer viewer;
// private EGLRenameAction renameAction;
// private EGLMoveAction moveAction;
private ListenerList fSelectionChangedListeners = new ListenerList();
private IPropertyChangeListener fPropertyChangeListener;
//EGL70Migration - need to test this
//private TextOperationAction fUndo;
//private TextOperationAction fRedo;
private UndoActionHandler fUndo;
private RedoActionHandler fRedo;
// private EGLMemberFilterActionGroup fMemberFilterActionGroup;
private TogglePresentationAction fTogglePresentation;
private EGLEditor editor;
public OutlinePage(IEGLDocument document, String fOutlinerContextMenuID, EGLEditor editor) {
this.document = document;
this.fOutlinerContextMenuID = fOutlinerContextMenuID;
this.factory = new OutlineAdapterFactory(document, editor);
this.editor = editor;
document.addModelChangeListener(this);
// BETH - figure out why Java adds a new show selected element only action
fTogglePresentation = new TogglePresentationAction();
fTogglePresentation.setEditor(editor);
fPropertyChangeListener = new IPropertyChangeListener() {
public void propertyChange(PropertyChangeEvent event) {
doPropertyChange(event);
}
};
EDTUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(fPropertyChangeListener);
}
private void doPropertyChange(PropertyChangeEvent event) {
if (viewer != null) {
if (PreferenceConstants.APPEARANCE_MEMBER_SORT_ORDER.equals(event.getProperty())) {
viewer.refresh(document.getNewModelEGLFile(),false);
}
}
}
/*
* @see ISelectionProvider#addSelectionChangedListener(ISelectionChangedListener)
*/
public void addSelectionChangedListener(ISelectionChangedListener listener) {
fSelectionChangedListeners.add(listener);
if (viewer != null) {
viewer.addPostSelectionChangedListener(listener);
}
}
/*
* @see ISelectionProvider#removeSelectionChangedListener(ISelectionChangedListener)
*/
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
fSelectionChangedListeners.remove(listener);
if (viewer != null) {
viewer.removePostSelectionChangedListener(listener);
}
}
// protected void contextMenuAboutToShow(IMenuManager menu) {
// boolean generateActionEnabled;
//
// menu.add(expandAction);
// menu.add(collapseAction);
//
// menu.add(new Separator());
// menu.add(removeAction);
//
//
// IMenuManager submenuRef = new MenuManager(UINlsStrings.Refactor);
// if(renameAction.canRun((IStructuredSelection) getSelection())) {
// submenuRef.add(renameAction);
// }
//
// if(moveAction.canRun((IStructuredSelection) getSelection())) {
// submenuRef.add(moveAction);
// }
//
// if(submenuRef.getItems().length != 0) {
// menu.add(new Separator());
// menu.add(submenuRef);
// }
//
// menu.add(new Separator());
// org.eclipse.edt.ide.ui.internal.ui.search.ContextMenuSearchAction.appendToMenu(menu,viewer,((IFileEditorInput) getEditorInput()).getFile(),null);
//
// menu.add(new Separator());
// addOpenInPartsRefAction(menu);
// addOrganizeFormsAction(menu);
// menu.add(generateAction);
// menu.add(generateWithWizardAction);
//
// menu.add(new Separator());
// menu.add(retrieveSQLAction);
// menu.add(createDataItemAction);
//
// // Add this standard additions group so that other people can add
// // actions to the outline view
// menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
//
// generateActionEnabled = false;
//
// IStructuredSelection selection = (IStructuredSelection) getTreeViewer().getSelection();
//
// removeAction.setEnabled(!selection.isEmpty());
//
// if (selection.size() == 1) {
// generateActionEnabled = isGenerationValid(selection.getFirstElement());
// retrieveSQLAction.setEnabled(isRetrieveSQLValid(selection.getFirstElement()));
// removeAction.setEnabled(!(selection.getFirstElement() instanceof ImportGroup));
// }
//
// createDataItemAction.setEnabled(EGLSQLEditorUtility.isCreateDataItemValid(selection));
// generateAction.setEnabled(generateActionEnabled);
// generateWithWizardAction.setEnabled(generateActionEnabled);
// }
//
// /**
// * @param menu
// */
// private void addOrganizeFormsAction(IMenuManager menu) {
// if (organizeFormsAction.canRun((IStructuredSelection) getSelection())) {
// menu.add(organizeFormsAction);
// }
// }
//
// private EGLRenameAction createRenameAction() {
// EGLRenameAction renameAction = new EGLRenameAction(getSite(), this);
// renameAction.setActionDefinitionId(EGLEditor.RENAME_ActionDef_ID);
// return renameAction;
// }
//
// private EGLMoveAction createMoveAction() {
// EGLMoveAction moveAction = new EGLMoveAction(getSite(), this);
// moveAction.setActionDefinitionId(EGLEditor.MOVE_ActionDef_ID);
// return moveAction;
// }
//
// private EGLOrganizeFormsAction createOrganizeFormsAction(){
// EGLOrganizeFormsAction organizeAction = new EGLOrganizeFormsAction(getSite(), this);
// return organizeAction;
// }
//
//
// /**
// * Add open in parts reference action if a program, pagehandler or library is selected
// * @param menu
// */
// private void addOpenInPartsRefAction(IMenuManager menu) {
// menu.add(openInPartsRefAction);
// IStructuredSelection selection = (IStructuredSelection) getTreeViewer().getSelection();
// if (selection.size() == 1) {
// Object selectedElement = selection.getFirstElement();
// if (selectedElement != null)
// if(selectedElement instanceof Program ||
// selectedElement instanceof Handler || selectedElement instanceof Library ||
// selectedElement instanceof Service)
// openInPartsRefAction.setEnabled(true);
// else openInPartsRefAction.setEnabled(false);
// }
// }
//
// private void createActions() {
// expandAction = new EGLOutlineExpandCollapseAction(getTreeViewer(), EGLOutlineExpandCollapseAction.EXPAND);
// collapseAction = new EGLOutlineExpandCollapseAction(getTreeViewer(), EGLOutlineExpandCollapseAction.COLLAPSE);
// openInPartsRefAction = new EGLOutlineOpenInPartsRefAction(UINlsStrings.PartsReferenceNodeOpenPartLabel, this);
// //moveAction = new EGLMoveAction(getSite());
// generateAction = new EGLOutlineGenerateAction(UINlsStrings.GenerateActionLabel, this);
// generateWithWizardAction =
// new EGLOutlineGenerateWithWizardAction(UINlsStrings.GenerateWithWizardActionLabel, this);
// removeAction = new EGLOutlineRemoveAction(UINlsStrings.RemoveActionLabel, this);
// sortByOrderAction = new EGLOutlineSortAction(getTreeViewer(), EGLOutlineSorter.ORDER);
// sortByNameAction = new EGLOutlineSortAction(getTreeViewer(), EGLOutlineSorter.NAME);
// sortByTypeAction = new EGLOutlineSortAction(getTreeViewer(), EGLOutlineSorter.PART_TYPE);
//
// retrieveSQLAction = new EGLSQLRetrieveAction(UINlsStrings.getResourceBundleForConstructedKeys(), "RetrieveSQL.", editor); //$NON-NLS-1$
// createDataItemAction = new EGLCreateDataItemAction(getTreeViewer(), UINlsStrings.getResourceBundleForConstructedKeys(), "CreateDataItem.", editor); //$NON-NLS-1$
//
// renameAction = createRenameAction();
// moveAction = createMoveAction();
// organizeFormsAction = createOrganizeFormsAction();
//
// //EGL70Migration - need to test
// fUndo = (UndoActionHandler) editor.getAction(ITextEditorActionConstants.UNDO);
// fRedo = (RedoActionHandler) editor.getAction(ITextEditorActionConstants.REDO);
//
// }
// Creates and registers the menu manager and creates the context menu itself
// public void createContextMenu() {
//
// // Create menu manager
// MenuManager manager = new MenuManager(fOutlinerContextMenuID, fOutlinerContextMenuID);
//
// // set menu manager options and add listener
// manager.setRemoveAllWhenShown(true);
// manager.addMenuListener(new IMenuListener() {
// public void menuAboutToShow(IMenuManager manager) {
// contextMenuAboutToShow(manager);
// }
// });
//
// // Register menu manager (needs to be after listeners are added)
// getSite().registerContextMenu(Activator.getPluginId() + ".outline", manager, viewer); //$NON-NLS-1$
//
// // Create context menu
// Control c = getTreeViewer().getControl();
// Menu menu = manager.createContextMenu(c);
// c.setMenu(menu);
// }
/* (non-Javadoc)
* @see org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(Composite parent) {
super.createControl(parent);
viewer = getTreeViewer();
viewer.setContentProvider(new OutlineContentProvider(factory));
viewer.setLabelProvider(new OutlineLabelProvider(factory));
viewer.setComparer(new IElementComparer(){
public boolean equals(Object a, Object b){
IOutlineAdapter aAdapter = factory.adapt(a);
IOutlineAdapter bAdapter = factory.adapt(b);
IRegion aRegion = aAdapter.getHighlightRange(a);
IRegion bRegion = bAdapter.getHighlightRange(b);
//need to compare the region, for constant field in form group, the text is the same, but they could be different node
return aAdapter == bAdapter && aAdapter.getText(a).equalsIgnoreCase(bAdapter.getText(b)) && aRegion.equals(bRegion) ;
}
/**
* Returns the hash code for the given element.
*
* @return the hash code for the given element
*/
public int hashCode(Object element){
return factory.adapt(element).getText(element).hashCode();
}
});
Object[] listeners = fSelectionChangedListeners.getListeners();
for (int i = 0; i < listeners.length; i++) {
fSelectionChangedListeners.remove(listeners[i]);
viewer.addPostSelectionChangedListener((ISelectionChangedListener) listeners[i]);
}
getSite().setSelectionProvider(viewer);
// createActions();
// registerActions();
// createContextMenu();
viewer.setInput(document.getNewModelEGLFile());
// Commented out debug actions for M3
// addDebugAction();
}
public void dispose() {
if (editor == null)
return;
if (document != null)
document.removeModelChangeListener(this);
// if (fMemberFilterActionGroup != null) {
// fMemberFilterActionGroup.dispose();
// fMemberFilterActionGroup = null;
// }
editor.outlinePageClosed();
editor = null;
fSelectionChangedListeners.clear();
fSelectionChangedListeners = null;
if (fPropertyChangeListener != null) {
EDTUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(fPropertyChangeListener);
fPropertyChangeListener = null;
}
if (submenu != null) {
submenu.dispose();
submenu = null;
}
fTogglePresentation.setEditor(null);
viewer = null;
super.dispose();
}
public IEGLDocument getDocument() {
return document;
}
public EGLEditor getEditor() {
return editor;
}
// Make this public so actions can get to it
public TreeViewer getTreeViewer() {
return super.getTreeViewer();
}
/**
* This implements {@link com.ibm.jface.action.IMenuListener} to help fill the context menus with contributions from the Edit menu.
*/
public void menuAboutToShow(IMenuManager menuManager) {
//
// // figure out which action to check...
// // set everything to false first..
// sortByOrderAction.setChecked(false);
// sortByNameAction.setChecked(false);
// sortByTypeAction.setChecked(false);
//
// TreeViewer viewer = getTreeViewer();
// if (viewer.getSorter() != null) {
// switch (((EGLOutlineSorter) viewer.getSorter()).getType()) {
// case EGLOutlineSorter.NAME :
// {
// sortByNameAction.setChecked(true);
// break;
// }
// case EGLOutlineSorter.PART_TYPE :
// {
// sortByTypeAction.setChecked(true);
// break;
// }
// default :
// ;
// }
// } else {
// sortByOrderAction.setChecked(true);
// }
// BETH -required to force the check to show on the correct sort option
if (submenu != null)
submenu.updateAll(true);
}
// Select the specific part in the outline view
public void select(Object reference) {
if (viewer != null) {
ISelection s = viewer.getSelection();
if (s instanceof IStructuredSelection) {
IStructuredSelection ss = (IStructuredSelection) s;
List elements = ss.toList();
if (!elements.contains(reference)) {
s = (reference == null ? StructuredSelection.EMPTY : new StructuredSelection(reference));
viewer.setSelection(s, true);
}
}
}
}
private Reconciler reconciler = new Reconciler();
private boolean reconcilerScheduled;
private static final int DELAY = 2000;
private class Reconciler implements Runnable {
public void run() {
long currentTime = System.currentTimeMillis();
if (currentTime - document.getLastUpdateTime() < DELAY) {
if (!getTreeViewer().getControl().isDisposed()) {
getTreeViewer().getControl().getDisplay().timerExec(DELAY, reconciler);
}
return;
}
if (!getTreeViewer().getControl().isDisposed()) {
getTreeViewer().getControl().setRedraw(false);
document.reconcile();
// getTreeViewer().setInput(document.getNewModelEGLFile());
getTreeViewer().refresh(document.getNewModelEGLFile(),true);
getTreeViewer().getControl().setRedraw(true);
}
reconcilerScheduled = false;
}
}
public void modelChanged() {
if (!reconcilerScheduled && getTreeViewer() != null && !getTreeViewer().getControl().isDisposed()) {
getTreeViewer().getControl().getDisplay().timerExec(DELAY, reconciler);
}
}
// private void registerActions() {
//
// IActionBars actionBars = getSite().getActionBars();
// IMenuManager menu = actionBars.getMenuManager();
// IToolBarManager toolBarManager = actionBars.getToolBarManager();
//
// // Hook up the Edit menu undo/redo actions
// actionBars.setGlobalActionHandler(ITextEditorActionConstants.UNDO, fUndo);
// actionBars.setGlobalActionHandler(ITextEditorActionConstants.REDO, fRedo);
//
// menu.addMenuListener(this);
//
// submenu = new MenuManager(UINlsStrings.SortMenuLabel);
// menu.add(submenu);
// submenu.add(sortByNameAction);
// submenu.add(sortByTypeAction);
// submenu.add(new Separator());
// submenu.add(sortByOrderAction);
//
// actionBars.setGlobalActionHandler(TOGGLE_PRESENTATION, fTogglePresentation);
//
// if (toolBarManager != null) {
// // toolBarManager.add(new ClassOnlyAction());
// // toolBarManager.add(new LexicalSortingAction());
//
// fMemberFilterActionGroup = new EGLMemberFilterActionGroup(getTreeViewer(), "TreeViewer"); //$NON-NLS-1$
// // fMemberFilterActionGroup= new EGLMemberFilterActionGroup(fOutlineViewer, "EGLOutlineViewer"); //$NON-NLS-1$
// fMemberFilterActionGroup.contributeToToolBar(toolBarManager);
// }
//
// IContextService contextService = (IContextService)getSite().getService(IContextService.class);
// contextService.activateContext("org.eclipse.edt.ide.ui.contexts.refactoring");
//
// actionBars.setGlobalActionHandler(EGLEditor.RENAME_ID, renameAction);
// actionBars.setGlobalActionHandler(EGLEditor.MOVE_ID, moveAction);
// actionBars.setGlobalActionHandler(EGLEditor.ORGANIZE_FORMS_ID, organizeFormsAction);
// }
// private void addDebugAction() {
// IToolBarManager manager = getSite().getActionBars().getToolBarManager();
//
// Action printPrimitiveParserTreeAction = new Action() {
// public void run() {
// ErrorParser parser = new ErrorParser();
// try {
// ParseTreePrinter.print(parser.parse(document.get()));
// } catch (ParseErrorException e) {
// // We don't need to worry about it
// }
// }
// };
// printPrimitiveParserTreeAction.setImageDescriptor(EGLUIPlugin.getImageDescriptor("activehelpview"));
//
// Action printTSNTreeAction = new Action() {
// public void run() {
// EGLParser parser = new EGLParser();
// try {
// TSNParseTreePrinter.print((INode) parser.parse(document.get()));
// } catch (ParseErrorException e) {
// // We don't need to worry about it
// }
// }
// };
// printTSNTreeAction.setImageDescriptor(EGLUIPlugin.getImageDescriptor("eglpgm"));
//
// Action refreshAction = new Action() {
// public void run() {
// long l = System.currentTimeMillis();
// getTreeViewer().getControl().setRedraw(false);
// getTreeViewer().refresh();
// getTreeViewer().getControl().setRedraw(true);
// System.out.println("Refresh time: " + (System.currentTimeMillis() - l));
// }
// };
// refreshAction.setImageDescriptor(EGLUIPlugin.getImageDescriptor("right_sibling"));
//
// manager.add(printPrimitiveParserTreeAction);
// manager.add(printTSNTreeAction);
// manager.add(refreshAction);
// }
/**
* @return
*/
public IEditorInput getEditorInput() {
return editor.getEditorInput();
}
public void setInput(IEGLDocument newDocument) {
if (document != null)
document.removeModelChangeListener(this);
document = newDocument;
if (document != null) {
document.addModelChangeListener(this);
}
if (viewer != null) {
viewer.setInput(newDocument.getNewModelEGLFile());
}
}
// private boolean isRetrieveSQLValid(Object selectedElement) {
// if (selectedElement != null && selectedElement instanceof Record) {
// return SQLUtility.isSQLRecordPart((Record) selectedElement);
// }
// return false;
// }
public void refresh() {
if (getTreeViewer() != null) {
document.reconcile();
getTreeViewer().refresh(document.getNewModelEGLFile(),true);
}
}
public IFile getFile() {
return ((IFileEditorInput) getEditorInput()).getFile();
}
}