/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.ui.outline;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.views.contentoutline.ContentOutlinePage;
import org.teiid.designer.ui.PluginConstants;
import org.teiid.designer.ui.UiConstants;
import org.teiid.designer.ui.UiPlugin;
import org.teiid.designer.ui.actions.ModelerActionService;
import org.teiid.designer.ui.actions.ModelerSpecialActionManager;
import org.teiid.designer.ui.actions.SortModelContentsAction;
import org.teiid.designer.ui.editors.ModelEditor;
import org.teiid.designer.ui.editors.ModelEditorPage;
import org.teiid.designer.ui.editors.ModelEditorPageOutline;
/**
* ModelOutlinePage is the ContentOutlinePage for the ModelEditor. It contains a PageBook which can display a TreeViewer of the
* Model, plus any other controls that are contributed by ModelEditorPage extensions.
*
* @since 8.0
*/
public class ModelOutlinePage extends ContentOutlinePage {
private static final ImageDescriptor blankIcon = UiPlugin.getDefault().getImageDescriptor(PluginConstants.Images.BLANK_ICON);
ModelEditor modelEditor;
private PageBook pageBook;
private ModelEditorPageOutline currentViewer;
/** the ModelOutlineTree, which is always available in the ContentOutlinePage */
ModelOutlineTreeViewer viewer;
/** map of key=ModelEditorPage classname, value = ModelEditorPageOutline instance */
private HashMap contributionMap = new HashMap();
/** list of ModelEditorPageOutlines that have been initialized, to facility lazy loading */
private ArrayList initList = new ArrayList();
/** the action for showing the ModelOutlineTreeViewer */
private IAction modelOutlineAction;
/** the action for showing the active ModelEditorPage's outline contribution */
private IAction contributionAction;
/** action allowing user to directly refresh tree */
IAction refreshAction;
/** action allowing user to directly refresh tree */
private IAction collapseAllAction;
/** set to true once this object has been fully initialized and placed in the Workbench. */
private boolean hasInitialized = false;
/** needed for key listening */
private KeyAdapter kaKeyAdapter;
public ModelOutlinePage( ModelEditor editor ) {
super();
this.modelEditor = editor;
}
@Override
public void init( IPageSite pageSite ) {
super.init(pageSite);
}
/**
* Called by the ModelEditor when instantiating ModelEditorPage extensions, this method adds a page to the page book for the
* ModelEditorPageOutline, and an action on the toolbar to show/hide it.
*/
public void addOutlineContribution( ModelEditorPage page ) {
ModelEditorPageOutline contribution = page.getOutlineContribution();
if (contribution != null) {
final String id = page.getClass().getName();
// store the contribution in a HashMap so we can enable/disable based on the active ModelEditorPage
contributionMap.put(id, contribution);
}
}
@Override
public void createControl( Composite parent ) {
// register global actions
ModelerActionService service = getModelerActionService();
service.registerDefaultGlobalActions(getSite().getActionBars());
pageBook = new PageBook(parent, SWT.NONE);
// the ModelOutlineTreeViewer is always available, no matter what ModelEditorPage is showing
viewer = new ModelOutlineTreeViewer(this.modelEditor);
final String id = viewer.getClass().getName();
viewer.init(getSite());
viewer.createControl(pageBook);
// Preview Data Action from DQP Ui. If Exists, place in toolbar
IAction previewAction = ModelerSpecialActionManager.getAction(UiConstants.Extensions.PREVIEW_DATA_ACTION_ID);
if (previewAction != null) {
getSite().getActionBars().getToolBarManager().add(previewAction);
getSite().getActionBars().getToolBarManager().add(new Separator());
}
IToolBarManager tbm = getSite().getActionBars().getToolBarManager();
modelOutlineAction = new Action() {
@Override
public void run() {
showPage(id);
refreshAction.setEnabled(true);
}
};
modelOutlineAction.setToolTipText(viewer.getToolTipText());
modelOutlineAction.setImageDescriptor(viewer.getIcon());
contributionAction = new Action() {
@Override
public void run() {
showPage(modelEditor.getCurrentPage().getClass().getName());
refreshAction.setEnabled(false);
}
};
contributionAction.setImageDescriptor(blankIcon);
contributionAction.setEnabled(false);
contributionAction.setChecked(false);
tbm.add(contributionAction);
tbm.add(modelOutlineAction);
tbm.add(new Separator());
tbm.add(new SortModelContentsAction(viewer.getTree()));
// add refresh tree action
refreshAction = new Action() {
@Override
public void run() {
viewer.getTree().refresh();
}
};
refreshAction.setImageDescriptor(UiPlugin.getDefault().getImageDescriptor(PluginConstants.Images.REFRESH_ICON));
refreshAction.setToolTipText(UiConstants.Util.getString("ModelOutlinePage.refreshAction.tooltip")); //$NON-NLS-1$
refreshAction.setText(UiConstants.Util.getString("ModelOutlinePage.refreshAction.text")); //$NON-NLS-1$
tbm.add(refreshAction);
refreshAction.setEnabled(true);
// add refresh tree action
refreshAction = new Action() {
@Override
public void run() {
viewer.getTree().refresh();
}
};
tbm.add(new Separator());
collapseAllAction = new Action() {
@Override
public void run() {
viewer.getTree().collapseAll();
}
};
collapseAllAction.setImageDescriptor(UiPlugin.getDefault().getImageDescriptor(PluginConstants.Images.COLLAPSE_ALL_ICON));
collapseAllAction.setToolTipText(UiConstants.Util.getString("ModelOutlinePage.collapseAllAction.tooltip")); //$NON-NLS-1$
collapseAllAction.setText(UiConstants.Util.getString("ModelOutlinePage.collapseAllAction.text")); //$NON-NLS-1$
tbm.add(collapseAllAction);
collapseAllAction.setEnabled(true);
hasInitialized = true;
if (this.modelEditor.getCurrentPage() instanceof ModelEditorPage) {
setActiveEditorPage((ModelEditorPage)this.modelEditor.getCurrentPage());
}
showPage(viewer.getClass().getName());
}
private ModelerActionService getModelerActionService() {
return (ModelerActionService)UiPlugin.getDefault().getActionService(getSite().getPage());
}
/**
* Called by ModelEditor to indicate that a different ModelEditorPage has become activated in the multi-page editor tab panel.
* This class responds by looking up the outline page contribution for that ModelEditorPage and, if one exists, making it
* available in the outline.
*
* @param page the just-activated page in the ModelEditor.
*/
// swjTODO: figure out the logic that should fire if the page changes while a contribution is showing.
public void setActiveEditorPage( ModelEditorPage page ) {
if (hasInitialized) {
ModelEditorPageOutline contribution = (ModelEditorPageOutline)contributionMap.get(page.getClass().getName());
if (contribution != null) {
contributionAction.setToolTipText(contribution.getToolTipText());
contributionAction.setImageDescriptor(contribution.getIcon());
contributionAction.setEnabled(contribution.isEnabled());
refreshAction.setEnabled(false);
} else {
contributionAction.setEnabled(false);
contributionAction.setToolTipText(null);
contributionAction.setImageDescriptor(blankIcon);
showPage(viewer.getClass().getName());
refreshAction.setEnabled(false);
}
}
}
@Override
public void dispose() {
// dispose all contributions to this panel
for (Iterator iter = contributionMap.values().iterator(); iter.hasNext();) {
((ModelEditorPageOutline)iter.next()).dispose();
}
if (viewer != null) {
viewer.dispose();
}
super.dispose();
}
@Override
public Control getControl() {
return pageBook;
}
public Object getCurrentViewer() {
return currentViewer;
}
@Override
public void setFocus() {
// we cannot call super's setFocus, since its viewer is not initialized
// (we never called super.createControl)
if (currentViewer != null) {
currentViewer.getControl().setFocus();
} // endif
}
/**
* Called by the toolbar actions, determines which outline page to show.
*
* @param id the class name of either the ModelOutlineTreeViewer, or the active ModelEditorPage who's contribution to this
* panel should be shown.
*/
protected void showPage( String id ) {
if (!hasInitialized) {
return;
}
Control pageToShow = null;
if (id.equals(ModelOutlineTreeViewer.class.getName())) {
contributionAction.setChecked(false);
modelOutlineAction.setChecked(true);
pageToShow = viewer.getControl();
currentViewer = viewer;
} else {
ModelEditorPageOutline contribution = (ModelEditorPageOutline)contributionMap.get(id);
if (contribution != null) {
boolean isEnabled = true;
// make sure the contribution's Control has been created.
if (!initList.contains(id)) {
// only create the outline's control once it is about to be viewed.
contribution.createControl(pageBook);
initList.add(id);
isEnabled = contribution.isEnabled();
}
if (isEnabled) {
contributionAction.setChecked(true);
modelOutlineAction.setChecked(false);
pageToShow = contribution.getControl();
currentViewer = contribution;
} else {
contributionAction.setChecked(false);
contributionAction.setEnabled(false);
}
}
}
if (pageToShow != null) {
initKeyListener();
pageBook.showPage(pageToShow);
}
}
/**
* Create the KeyListener for capturing DEL and F2 (rename?)
*/
private void initKeyListener() {
// create the adapter
if (kaKeyAdapter == null) {
kaKeyAdapter = new KeyAdapter() {
@Override
public void keyReleased( KeyEvent event ) {
handleKeyEvent(event);
}
};
}
// add the adapter as a listener
if (currentViewer != null) {
currentViewer.getControl().removeKeyListener(kaKeyAdapter);
currentViewer.getControl().addKeyListener(kaKeyAdapter);
}
}
/**
* On certain keys execute certain actions
*/
void handleKeyEvent( KeyEvent event ) {
if (event.stateMask != 0) return;
if (event.keyCode == SWT.F2) {
// rename action
try {
IAction actRename = getModelerActionService().getAction(ActionFactory.RENAME.getId());
if (actRename != null && actRename.isEnabled()) {
actRename.run();
}
} catch (CoreException ce) {
}
} else if (event.character == SWT.DEL) {
// delete action
IAction actDelete = this.getSite().getActionBars().getGlobalActionHandler(ActionFactory.DELETE.getId());
if (actDelete != null && actDelete.isEnabled()) {
actDelete.run();
}
}
}
}