/* * 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.favorites; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.teiid.core.designer.event.EventObjectListener; import org.teiid.core.designer.util.CoreStringUtil; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.ui.IModelerCacheListener; import org.teiid.designer.ui.ModelerCacheEvent; import org.teiid.designer.ui.PluginConstants; import org.teiid.designer.ui.UiConstants; import org.teiid.designer.ui.UiPlugin; import org.teiid.designer.ui.actions.IModelObjectActionContributor; import org.teiid.designer.ui.actions.ModelerActionService; import org.teiid.designer.ui.common.actions.ExtendedMenuManager; import org.teiid.designer.ui.common.eventsupport.SelectionUtilities; import org.teiid.designer.ui.common.util.OrderableViewerSorter; import org.teiid.designer.ui.common.util.WidgetFactory; import org.teiid.designer.ui.common.util.WidgetUtil; import org.teiid.designer.ui.common.widget.AbstractTableLabelProvider; import org.teiid.designer.ui.editors.ModelEditor; import org.teiid.designer.ui.editors.ModelEditorManager; import org.teiid.designer.ui.properties.ModelObjectPropertySourceProvider; import org.teiid.designer.ui.search.ModelObjectFinderDialog; import org.teiid.designer.ui.viewsupport.ModelUtilities; /** * FavoritesView is a class designed to provide a table summary of user-defined EObjects or objects contained in models. The * objects can be added to this table in various ways and removed or cleared via the actions and toolbar buttons provided. * * @since 8.0 */ public class FavoritesView extends ViewPart implements ISelectionProvider, ISelectionListener, IModelerCacheListener, CoreStringUtil.Constants { private static final int NAME_COLUMN = 0; private static final int LOCATION_COLUMN = 1; private static final String ADD_TO_FAVORITES = "action.add.tooltip2"; //$NON-NLS-1$ private ModelObjectPropertySourceProvider propertySourceProvider; ILabelProvider nameLabelProvider = ModelUtilities.getModelObjectLabelProvider(); private ArrayList listenerList = new ArrayList(); TableViewer tableViewer; private boolean controlCreated = false; private EObjectModelerCache eObjCache; ISelection externalSelection; private ModelerActionService actionService; /** The ModelResource listener for file system changes on models and projects */ EventObjectListener modelResourceListener; /* * Static methods used obtain i18n.property strings for the string contants in this class */ private static String getString( final String stringId ) { return UiConstants.Util.getString("FavoritesView." + stringId); //$NON-NLS-1$ } private static String getString( final String stringId, Object value, Object value1 ) { if (value == null) return getString(stringId); if (value1 == null) return UiConstants.Util.getString("FavoritesView." + stringId, value); //$NON-NLS-1$ return UiConstants.Util.getString("FavoritesView." + stringId, value, value1); //$NON-NLS-1$ } private Action clearAction, openAction, editAction, addAction, removeAction, selectAllAction, deselectAllAction, findAction; /** * Base constructor */ public FavoritesView() { } /** * @see org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) * @since 4.2 */ @Override public void createPartControl( Composite parent ) { controlCreated = true; initTableViewer(parent); MenuManager popupMenuManager = new ExtendedMenuManager(); IMenuListener listener = new IMenuListener() { @Override public void menuAboutToShow( IMenuManager mng ) { fillContextMenu(mng); } }; popupMenuManager.addMenuListener(listener); popupMenuManager.setRemoveAllWhenShown(true); Menu menu = popupMenuManager.createContextMenu(tableViewer.getControl()); tableViewer.getControl().setMenu(menu); getSite().registerContextMenu(popupMenuManager, tableViewer); initActions(); fillToolBar(); getSite().setSelectionProvider(this); // Get the cache and wire it up eObjCache = UiPlugin.getDefault().getEObjectCache(); eObjCache.addCacheListener(this); // set initial state this.tableViewer.setInput(this); setActionsState(); packTable(); getSite().getWorkbenchWindow().getSelectionService().addSelectionListener(this); ISelection selection = getSite().getWorkbenchWindow().getSelectionService().getSelection(); if (selection != null) { selectionChanged(this, selection); } } /** * Helper method which takes care of creating table viewer, and wiring up listeners and providers. * * @param parent * @since 4.2 */ public void initTableViewer( Composite parent ) { this.tableViewer = WidgetFactory.createTableViewer(parent, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.FULL_SELECTION); final Table table = this.tableViewer.getTable(); table.setHeaderVisible(true); table.setLinesVisible(true); WidgetFactory.createTableColumn(table, getString("columns.name")); //$NON-NLS-1$ WidgetFactory.createTableColumn(table, getString("columns.location")); //$NON-NLS-1$} this.tableViewer.setContentProvider(new IStructuredContentProvider() { @Override public void dispose() { } @Override public Object[] getElements( final Object inputElement ) { return UiPlugin.getDefault().getEObjectCache().toArray(); } @Override public void inputChanged( final Viewer viewer, final Object oldInput, final Object newInput ) { } }); this.tableViewer.setLabelProvider(new AbstractTableLabelProvider() { @Override public Image getColumnImage( final Object element, final int column ) { if (column == NAME_COLUMN) { return nameLabelProvider.getImage(element); } return null; } @Override public String getColumnText( final Object element, final int column ) { switch (column) { case NAME_COLUMN: { return nameLabelProvider.getText(element); } case LOCATION_COLUMN: { return ModelerCore.getModelEditor().getFullPathToParent((EObject)element).makeRelative().toString(); } } return EMPTY_STRING; } }); this.tableViewer.setSorter(new OrderableViewerSorter()); this.tableViewer.addDoubleClickListener(new IDoubleClickListener() { @Override public void doubleClick( final DoubleClickEvent event ) { // Assume that we have an Open request here. if (SelectionUtilities.isSingleSelection(event.getSelection())) { EObject eObj = SelectionUtilities.getSelectedEObject(event.getSelection()); if (eObj != null) { ModelEditorManager.open(eObj, true); } } } }); tableViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged( final SelectionChangedEvent event ) { handleSelectionChanged(event.getSelection()); } }); } private ImageDescriptor getImageDescriptor( String imageId ) { return UiPlugin.getDefault().getImageDescriptor(imageId); } /* * Initialize view actions, set icons and action text. */ private void initActions() { editAction = new Action(getString("action.edit")) { //$NON-NLS-1$ @Override public void run() { if (SelectionUtilities.isSingleSelection(getSelection())) { EObject eObj = SelectionUtilities.getSelectedEObject(getSelection()); if (eObj != null) { ModelEditorManager.edit(eObj); } } } }; editAction.setEnabled(false); openAction = new Action(getString("action.open")) { //$NON-NLS-1$ @Override public void run() { if (SelectionUtilities.isSingleSelection(getSelection())) { EObject eObj = SelectionUtilities.getSelectedEObject(getSelection()); if (eObj != null) { ModelEditorManager.open(eObj, true); } } } }; openAction.setEnabled(false); selectAllAction = new Action(getString("action.selectAll")) { //$NON-NLS-1$ @Override public void run() { tableViewer.getTable().selectAll(); } }; selectAllAction.setEnabled(false); deselectAllAction = new Action(getString("action.deselectAll")) { //$NON-NLS-1$ @Override public void run() { tableViewer.getTable().deselectAll(); } }; deselectAllAction.setEnabled(false); addAction = new Action(getString("action.add")) {//$NON-NLS-1$ @Override public void run() { if (externalSelection != null) { Collection addedObjs = SelectionUtilities.getSelectedEObjects(externalSelection); if (!addedObjs.isEmpty()) { UiPlugin.getDefault().getEObjectCache().addAll(addedObjs); } } } }; addAction.setImageDescriptor(getImageDescriptor(PluginConstants.Images.ADD_ICON)); addAction.setToolTipText(getString("action.add.tooltip")); //$NON-NLS-1$ removeAction = new Action(getString("action.remove")) { //$NON-NLS-1$ @Override public void run() { UiPlugin.getDefault().getEObjectCache().removeAll(getSelectedEObjects()); } }; removeAction.setEnabled(false); removeAction.setImageDescriptor(getImageDescriptor(PluginConstants.Images.REMOVE_ICON)); removeAction.setToolTipText(getString("action.remove.tooltip")); //$NON-NLS-1$ clearAction = new Action(getString("action.clear")) { //$NON-NLS-1$ @Override public void run() { UiPlugin.getDefault().getEObjectCache().clear(); } }; clearAction.setEnabled(false); clearAction.setImageDescriptor(getImageDescriptor(PluginConstants.Images.CLEAR_ICON)); clearAction.setToolTipText(getString("action.clear.tooltip")); //$NON-NLS-1$ findAction = new Action(getString("action.find")) {//$NON-NLS-1$ @Override public void run() { Collection addedObjs = findObjects(); if (!addedObjs.isEmpty()) { UiPlugin.getDefault().getEObjectCache().addAll(addedObjs); } } }; findAction.setImageDescriptor(getImageDescriptor(PluginConstants.Images.FIND_METADATA)); findAction.setToolTipText(getString("action.find.tooltip")); //$NON-NLS-1$ } /* * Private method which sets the enabled state of actions defined and contained in this view. * This is business logic, in a sense. */ void setActionsState() { // Set up values and booleans for actions int nRows = tableViewer.getTable().getSelectionCount(); boolean rowsSelected = nRows > 0; boolean allRowsSelected = nRows == tableViewer.getTable().getItems().length; boolean tableHasRows = tableViewer.getTable().getItems().length > 0; // Actions requiring selection removeAction.setEnabled(rowsSelected); deselectAllAction.setEnabled(rowsSelected); selectAllAction.setEnabled(!allRowsSelected); // Actions requiring non-empty table clearAction.setEnabled(tableHasRows); // Edit Action boolean enableEdit = false; if (nRows == 1) { EObject eObj = SelectionUtilities.getSelectedEObject(getSelection()); if (eObj != null) enableEdit = ModelEditorManager.canEdit(eObj); // open requires that only one object is selected openAction.setEnabled(true); } editAction.setEnabled(enableEdit); // Add action requires tracking selections external to this view, so they can be "added" // to the view. setAddActionState(this); } /* * Internal method which determines the enabled state of the add button based on a cached * ISelection obtained through the selection listener. */ private void setAddActionState( IWorkbenchPart part ) { boolean enable = false; if (part != this) { if (externalSelection != null) { List selectedEObjects = SelectionUtilities.getSelectedEObjects(externalSelection); if (!selectedEObjects.isEmpty()) { int size = selectedEObjects.size(); String title = part.getTitle(); if (part instanceof ModelEditor) { title = ((ModelEditor)part).getCurrentPage().getTitle(); } String tString = getString(ADD_TO_FAVORITES, Integer.toString(size), title); enable = true; addAction.setToolTipText(tString); } } else { addAction.setToolTipText(getString("action.add.tooltip")); //$NON-NLS-1$ } } addAction.setEnabled(enable); } /* * Populates the View's toolbar */ private void fillToolBar() { IToolBarManager tbm = getViewSite().getActionBars().getToolBarManager(); tbm.add(findAction); tbm.add(new Separator()); tbm.add(addAction); tbm.add(removeAction); tbm.add(clearAction); } /* * Util method to layout table and resize cells, columns and rows. */ private void packTable() { WidgetUtil.pack(tableViewer.getTable()); } /** * @see org.eclipse.ui.IWorkbenchPart#dispose() * @since 4.2 */ @Override public void dispose() { eObjCache.removeCacheListener(this); getSite().getWorkbenchWindow().getSelectionService().removeSelectionListener(this); super.dispose(); } /** * This method is called from the view's popup menu listener. * * @param manager * @since 4.2 */ public void fillContextMenu( IMenuManager manager ) { manager.add(openAction); manager.add(editAction); manager.add(new Separator()); manager.add(selectAllAction); manager.add(deselectAllAction); manager.add(new Separator()); manager.add(findAction); manager.add(new Separator()); manager.add(removeAction); manager.add(clearAction); manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); contributePermanentActionsToContextMenu(manager); } /** * @see org.eclipse.ui.IWorkbenchPart#setFocus() * @since 4.2 */ @Override public void setFocus() { if (controlCreated) tableViewer.getControl().setFocus(); } /* * handles selection changed within the table, fires a new event and updates the actions state. */ void handleSelectionChanged( ISelection selection ) { fireSelectionChanged(new SelectionChangedEvent(this, selection)); setActionsState(); } /** * @param item * @since 4.2 */ public void addItem( final Object item ) { addItems(new Object[] {item}); } /** * @param items * @since 4.2 */ public void addItems( final Object[] items ) { if (items.length > 0) { tableViewer.add(items); setSelection(new StructuredSelection(items)); } setActionsState(); packTable(); } /** * @param items * @since 4.2 */ public void removeItems( final Object[] items ) { if (!tableViewer.getControl().isDisposed()) { tableViewer.remove(items); setActionsState(); packTable(); } } /** * Clears table view. Actaully, the table contents is really defined by the content provider, or EObject cache. If this cache * is cleared, the table is cleared, so all that needs to be done is a refresh. Removing single, or multiple rows, requires * specific removal, however. * * @since 4.2 */ public void removeAllItems() { this.tableViewer.refresh(); } /** * Removes single row/item from table. * * @param item * @since 4.2 */ public void removeItem( final Object item ) { removeItems(new Object[] {item}); } /* * Private utility method which extracts a list of EObjects from the selected table rows. */ Collection getSelectedEObjects() { List selected = SelectionUtilities.getSelectedEObjects(tableViewer.getSelection()); if (selected == null || selected.isEmpty()) return Collections.EMPTY_LIST; return selected; } /* * This method provides the user a dialog */ Collection findObjects() { Shell shell = UiPlugin.getDefault().getCurrentWorkbenchWindow().getShell(); ModelObjectFinderDialog dialog = new ModelObjectFinderDialog(shell); dialog.open(); if (dialog.getReturnCode() == Window.OK) { // get the selected model object Object[] selectedEOList = dialog.getResult(); if (selectedEOList != null && selectedEOList.length > 0) { Collection newList = new ArrayList(selectedEOList.length); for (int i = 0; i < selectedEOList.length; i++) { newList.add(selectedEOList[i]); } return newList; } } return Collections.EMPTY_LIST; } /** * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) * @since 4.2 */ @Override public void addSelectionChangedListener( ISelectionChangedListener listener ) { if (!listenerList.contains(listener)) { listenerList.add(listener); } } /** * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection() * @since 4.2 */ @Override public ISelection getSelection() { return tableViewer.getSelection(); } /** * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) * @since 4.2 */ @Override public void removeSelectionChangedListener( ISelectionChangedListener listener ) { listenerList.remove(listener); } /** * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection) * @since 4.2 */ @Override public void setSelection( ISelection selection ) { tableViewer.setSelection(selection, true); setActionsState(); } /* * Enough said */ private void fireSelectionChanged( SelectionChangedEvent event ) { for (Iterator iter = listenerList.iterator(); iter.hasNext();) { ((ISelectionChangedListener)iter.next()).selectionChanged(event); } } /** * Overridden from super to provide the PropertySheet for EObject, since EObject does not implement IAdaptable * * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) * @since 4.0 */ @Override public Object getAdapter( Class key ) { if (key.equals(IPropertySheetPage.class)) { if (propertySourceProvider == null) { propertySourceProvider = ModelUtilities.getPropertySourceProvider(); // new ModelObjectPropertySourceProvider(); } return propertySourceProvider.getPropertySheetPage(); } return super.getAdapter(key); } // IModeler Cache Listener /** * @see org.teiid.designer.ui.IModelerCacheListener#cacheChanged(org.teiid.designer.ui.ModelerCacheEvent) * @since 4.2 */ @Override public void cacheChanged( final ModelerCacheEvent theEvent ) { // make sure event handling in right thread getSite().getShell().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (!tableViewer.getControl().isDisposed()) { if (theEvent.isClear()) { removeAllItems(); } else if (theEvent.isAdd()) { addItems(theEvent.toArray()); } else if (theEvent.isDelete()) { removeItems(theEvent.toArray()); } else if (theEvent.isChange()) { Object[] changedElements = theEvent.toArray(); updateForChange(changedElements); } setActionsState(); } } }); } void updateForChange( Object[] changedElements ) { for (int i = 0; i < changedElements.length; i++) { Object obj = changedElements[i]; tableViewer.refresh(obj, true); } } /** * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart, * org.eclipse.jface.viewers.ISelection) * @since 4.2 */ @Override public void selectionChanged( IWorkbenchPart part, ISelection selection ) { if (part != this) { externalSelection = selection; setAddActionState(part); } } /** * Gives the <code>IModelObjectActionContributor</code>s a chance to contribute to the context menu * * @param theMenuMgr the context menu being contributed to * @param theSelection the current selection */ public void contributePermanentActionsToContextMenu( IMenuManager theMenuMgr ) { List contributors = getActionService().getModelObjectActionContributors(); ISelection selection = getSelection(); if (selection != null && !selection.isEmpty() || !SelectionUtilities.isSingleSelection(selection)) { for (int size = contributors.size(), i = 0; i < size; i++) { IModelObjectActionContributor contributor = (IModelObjectActionContributor)contributors.get(i); contributor.contributeToContextMenu(theMenuMgr, getSelection()); } } } /* * Utility method for accessing the Modeler Action Service so we can get the contributors and play in the external * action world. */ private ModelerActionService getActionService() { if (actionService == null) { actionService = (ModelerActionService)UiPlugin.getDefault().getActionService(getSite().getPage()); } return actionService; } }