diff --git a/org.fortiss.tooling.kernel.ui/plugin.xml b/org.fortiss.tooling.kernel.ui/plugin.xml index 314a127591cb64707af017c6b9a0b78b003f5221..9bb4a6ed075e7eb973b6f217659461e202235a3d 100644 --- a/org.fortiss.tooling.kernel.ui/plugin.xml +++ b/org.fortiss.tooling.kernel.ui/plugin.xml @@ -54,6 +54,12 @@ name="Kernel Introspection System Service (KISS)" restorable="true"> </view> + <view + class="org.fortiss.tooling.kernel.ui.internal.views.library.LibraryViewPart" + id="org.fortiss.tooling.kernel.ui.internal.views.library.LibraryViewPart" + name="Library View" + restorable="true"> + </view> </extension> <extension point="org.eclipse.core.runtime.adapters"> diff --git a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/ESharedImages.java b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/ESharedImages.java index dd65be1d1ee807db8460064d9b970847e6303ff0..d33fea62344c1654b5da296fb51a18098cb09eed 100644 --- a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/ESharedImages.java +++ b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/ESharedImages.java @@ -47,6 +47,9 @@ public enum ESharedImages { /** The navigator image. */ NAVIGATOR, + /** Library image. */ + LIBRARY, + /** Error (non-overlay) icon. */ ERROR, diff --git a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/views/DoubleClick.java b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/views/DoubleClick.java index fd00e7737c0bad903433c0adb67dad92220ff451..a94d27299814a93b0d8914050a5da7378a7eccd1 100644 --- a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/views/DoubleClick.java +++ b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/views/DoubleClick.java @@ -31,7 +31,7 @@ import org.fortiss.tooling.kernel.ui.util.EObjectSelectionUtils; * * @author hoelzl */ -class DoubleClick implements IDoubleClickListener { +public class DoubleClick implements IDoubleClickListener { /** Stores the use-raw-eobject flag. */ private final boolean useRawEObject; diff --git a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/views/library/LibraryTreeContentProvider.java b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/views/library/LibraryTreeContentProvider.java new file mode 100644 index 0000000000000000000000000000000000000000..e8a3e989a474ea6777b5386b92cc97ecf65a5e95 --- /dev/null +++ b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/views/library/LibraryTreeContentProvider.java @@ -0,0 +1,86 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2011 fortiss GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.kernel.ui.internal.views.library; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import org.conqat.ide.commons.ui.jface.TreeContentProviderBase; +import org.eclipse.emf.ecore.EObject; +import org.fortiss.tooling.kernel.extension.data.ITopLevelElement; +import org.fortiss.tooling.kernel.model.ILibrary; +import org.fortiss.tooling.kernel.model.ILibraryElementReference; +import org.fortiss.tooling.kernel.service.IPersistencyService; +import org.fortiss.tooling.kernel.ui.extension.IModelElementHandler; +import org.fortiss.tooling.kernel.ui.service.IModelElementHandlerService; + +/** + * Content provider for the model navigator tree viewer. + * + * @author hoelzlf + */ +public class LibraryTreeContentProvider extends TreeContentProviderBase { + + /** {@inheritDoc} */ + @Override + public Object[] getElements(Object inputElement) { + // delegate to the top-level element contexts of the persistency service + List<Object> result = new LinkedList<Object>(); + for(ITopLevelElement context : IPersistencyService.getInstance().getTopLevelElements()) { + EObject root = context.getRootModelElement(); + if(root instanceof ILibrary) { + result.add(root); + } + } + return result.toArray(); + } + + /** {@inheritDoc} */ + @Override + public Object[] getChildren(Object parent) { + // delegate to the model element handlers + if(parent instanceof EObject) { + EObject parentElement = (EObject)parent; + if(parentElement instanceof ILibraryElementReference) { + return new Object[0]; + } + IModelElementHandler<EObject> handler = + IModelElementHandlerService.getInstance().getModelElementHandler(parentElement); + if(handler != null) { + List<EObject> children = new ArrayList<EObject>(); + children.addAll(handler.getSubnodes(parentElement)); + children.addAll(handler.getSpecifications(parentElement)); + return children.toArray(); + } + } + return new Object[0]; + } + + /** {@inheritDoc} */ + @Override + public Object getParent(Object element) { + if(element instanceof EObject) { + EObject me = (EObject)element; + if(IPersistencyService.getInstance().isTopLevelElement(me)) { + // delegate to persistency service + return IPersistencyService.getInstance(); + } + return me.eContainer(); + } + return null; + } +} diff --git a/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/views/library/LibraryViewPart.java b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/views/library/LibraryViewPart.java new file mode 100644 index 0000000000000000000000000000000000000000..3cc353ad2937266788c8909c691a2102d9a8db1f --- /dev/null +++ b/org.fortiss.tooling.kernel.ui/src/org/fortiss/tooling/kernel/ui/internal/views/library/LibraryViewPart.java @@ -0,0 +1,348 @@ +/*-------------------------------------------------------------------------+ +| Copyright 2011 fortiss GmbH | +| | +| Licensed under the Apache License, Version 2.0 (the "License"); | +| you may not use this file except in compliance with the License. | +| You may obtain a copy of the License at | +| | +| http://www.apache.org/licenses/LICENSE-2.0 | +| | +| Unless required by applicable law or agreed to in writing, software | +| distributed under the License is distributed on an "AS IS" BASIS, | +| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | +| See the License for the specific language governing permissions and | +| limitations under the License. | ++--------------------------------------------------------------------------*/ +package org.fortiss.tooling.kernel.ui.internal.views.library; + +import static org.fortiss.tooling.kernel.ui.util.EObjectSelectionUtils.getEObjectElements; +import static org.fortiss.tooling.kernel.ui.util.EObjectSelectionUtils.getFirstElement; +import static org.fortiss.tooling.kernel.ui.util.EObjectSelectionUtils.getSelectionService; + +import java.util.List; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.DecoratingLabelProvider; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreePath; +import org.eclipse.jface.viewers.TreeSelection; +import org.eclipse.jface.viewers.TreeViewer; +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.ui.IDecoratorManager; +import org.eclipse.ui.IPartListener2; +import org.eclipse.ui.ISaveablePart; +import org.eclipse.ui.ISaveablesSource; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchPartConstants; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.Saveable; +import org.eclipse.ui.part.ViewPart; +import org.eclipse.ui.progress.UIJob; +import org.eclipse.ui.views.properties.IPropertySheetPage; +import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; +import org.fortiss.tooling.kernel.service.IPersistencyService; +import org.fortiss.tooling.kernel.ui.ESharedImages; +import org.fortiss.tooling.kernel.ui.extension.data.ContextMenuContextProvider; +import org.fortiss.tooling.kernel.ui.internal.NavigatorService; +import org.fortiss.tooling.kernel.ui.internal.views.DoubleClick; +import org.fortiss.tooling.kernel.ui.internal.views.NavigatorTreeContentComparator; +import org.fortiss.tooling.kernel.ui.internal.views.NavigatorTreeContentProvider; +import org.fortiss.tooling.kernel.ui.presentation.TutorialDefinitionModelElementLabelProvider; +import org.fortiss.tooling.kernel.ui.service.IActionService; +import org.fortiss.tooling.kernel.ui.service.IContextMenuService; +import org.fortiss.tooling.kernel.ui.service.INavigatorService; +import org.fortiss.tooling.kernel.ui.util.PropertiesConstantUtils; +import org.fortiss.tooling.kernel.ui.util.SelectionUtils; + +/** + * {@link ViewPart} of the model navigator provided by the tooling kernel. + * + * @author hoelzl + */ +public final class LibraryViewPart extends ViewPart implements ISelectionListener, + ISelectionChangedListener, ITabbedPropertySheetPageContributor, ContextMenuContextProvider, + ISaveablesSource, ISaveablePart { + + /** Stores the TreeViewer. */ + private TreeViewer viewer; + + /** Stores the menu manager. */ + private MenuManager menuManager; + + /** Stores the part listener for editor link support. */ + private IPartListener2 partListener; + + /** Stores the toggle action flag for editor linkage. */ + private boolean isLinkedWithEditor = false; + + /** Stores the toggle action for editor linkage. */ + private Action linkWithEditorAction = null; + + /** Dialog setting ID for the link with editor action flag. */ + private static final String LINK_WITH_EDITOR_FLAG = "navigatorSettingLinkWithEditor"; + + /** Element used to ensure that the selection of the {@link LibraryViewPart} is not empty. */ + private EObject backupElementToBeSelected; + + /** Element to be revealed during the UI update. */ + private Object elementToBeRevealed = null; + + /** Stores the UI update job. */ + private final UIJob updateUI = new UIJob("Update Library View") { + @Override + public IStatus runInUIThread(IProgressMonitor monitor) { + if(viewer.getControl().isDisposed()) { + return Status.OK_STATUS; + } + IActionService.getInstance().refresh(); + viewer.refresh(); + + LibraryViewPart.this.refreshPartTitleAndImage(); + + // Ensure that the selection of the {@link NavigatorViewPart} is not empty. Otherwise + // undo/redo (and also other global commands) is not enabled when model elements are + // added directly using the context menu of the model navigator. + ISelection selection = viewer.getSelection(); + if(selection instanceof TreeSelection && !selection.isEmpty()) { + Object firstSelectedElement = ((TreeSelection)selection).getFirstElement(); + if(firstSelectedElement instanceof EObject) { + // Preserve container of current element. This is required to determine a valid + // model element in case the next operation is to delete the currently selected + // element + backupElementToBeSelected = ((EObject)firstSelectedElement).eContainer(); + } + } else if(backupElementToBeSelected != null) { + // Selection would be empty. Use backup element to force selection to the container + // of the element that has been selected last. + TreePath treePath = new TreePath(new Object[] {backupElementToBeSelected}); + viewer.setSelection(new TreeSelection(treePath)); + backupElementToBeSelected = null; + } + + if(elementToBeRevealed != null) { + revealModelElement(elementToBeRevealed); + elementToBeRevealed = null; + } + + firePropertyChange(IWorkbenchPartConstants.PROP_DIRTY); + return Status.OK_STATUS; + } + }; + + // /** Constructor. */ + // public LibraryViewPart() { + // ((NavigatorService)INavigatorService.getInstance()).setNavigatorViewPart(this); + // } + + /** {@inheritDoc} */ + @Override + public void createPartControl(Composite parent) { + viewer = new TreeViewer(parent, SWT.MULTI); + + // NOTE that the order of this is important. See also JDT package + // explorer. + IDecoratorManager decoratorManager = PlatformUI.getWorkbench().getDecoratorManager(); + viewer.setLabelProvider( + new DecoratingLabelProvider(new TutorialDefinitionModelElementLabelProvider(), + decoratorManager.getLabelDecorator())); + viewer.setContentProvider(new LibraryTreeContentProvider()); + viewer.setComparator(new NavigatorTreeContentComparator()); + + getSite().setSelectionProvider(viewer); + createContextMenu(); + viewer.addSelectionChangedListener(this); + + viewer.setInput(IPersistencyService.getInstance()); + + viewer.addDoubleClickListener(new DoubleClick()); + + IActionService.getInstance().registerGlobalActions(getViewSite().getActionBars()); + + getSelectionService().addSelectionListener(this); + + // getSite().getPage().addPartListener(partListener); + + refreshPartTitleAndImage(); + } + + /** Sets the library view to be active. */ + public void setLibraryViewActive() { + NavigatorTreeContentProvider contentProvider = + (NavigatorTreeContentProvider)viewer.getContentProvider(); + if(!contentProvider.isLibraryViewActive()) { + contentProvider.toggleLibraryView(); + viewer.refresh(); + } + } + + /** Creates the context menu. */ + private void createContextMenu() { + menuManager = IContextMenuService.getInstance().createDefaultContextMenu(this); + + Menu contextMenu = menuManager.createContextMenu(viewer.getControl()); + viewer.getControl().setMenu(contextMenu); + + getSite().registerContextMenu(menuManager, viewer); + } + + /** {@inheritDoc} */ + @Override + public void setFocus() { + viewer.getControl().setFocus(); + } + + /** Reveals the given element in the navigator view. */ + public void revealModelElement(Object element) { + if(element == null) { + return; + } + if(!viewer.getExpandedState(element)) { + viewer.expandToLevel(element, 2); + } + viewer.setSelection(new StructuredSelection(element), true); + } + + /** {@inheritDoc} */ + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + IActionService.getInstance().refresh(); + // do not fire property change here, since it was not the viewers + // selection that changed but the workbench-wide selection + } + + /** {@inheritDoc} */ + @Override + public void selectionChanged(SelectionChangedEvent event) { + // Ignore programmatic selection of backup model element + if(backupElementToBeSelected != null) { + return; + } + + IActionService.getInstance().refresh(); + // Sync selection of active editor with model navigator + SelectionUtils.setSelection(getSelectedModelElementList(), false, true); + + // fire upon viewer selection change + firePropertyChange(IWorkbenchPartConstants.PROP_DIRTY); + } + + /** {@inheritDoc} */ + @Override + public void dispose() { + ((NavigatorService)INavigatorService.getInstance()).setNavigatorViewPart(null); + + getSelectionService().removeSelectionListener(this); + getSite().setSelectionProvider(null); + + // getSite().getPage().removePartListener(partListener); + + super.dispose(); + } + + /** {@inheritDoc} */ + @Override + public String getContributorId() { + return PropertiesConstantUtils.TABBED_PROPERTY_CONTRIBUTOR_ID; + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override + public <S> S getAdapter(Class<S> adapter) { + if(adapter == IPropertySheetPage.class) { + return (S)new TabbedPropertySheetPage(this); + } + return super.getAdapter(adapter); + } + + /** Refreshes the navigator view. */ + public void refresh() { + updateUI.schedule(); + } + + /** Refreshes the part's header image and title. */ + private void refreshPartTitleAndImage() { + String partName = "Library"; + Image partImage = ESharedImages.LIBRARY.getImage(); + setPartName(partName); + setTitleImage(partImage); + } + + /** {@inheritDoc} */ + @Override + public Saveable[] getSaveables() { + return INavigatorService.getInstance().getSaveables(); + } + + /** {@inheritDoc} */ + @Override + public Saveable[] getActiveSaveables() { + return INavigatorService.getInstance().getActiveSaveables(); + } + + /** {@inheritDoc} */ + @Override + public void doSave(IProgressMonitor monitor) { + // ignore. SaveableSource is used instead. + } + + /** {@inheritDoc} */ + @Override + public void doSaveAs() { + // ignore + } + + /** {@inheritDoc} */ + @Override + public boolean isDirty() { + return IPersistencyService.getInstance().isDirty(); + } + + /** {@inheritDoc} */ + @Override + public boolean isSaveAsAllowed() { + return false; + } + + /** {@inheritDoc} */ + @Override + public boolean isSaveOnCloseNeeded() { + return isDirty(); + } + + /** {@inheritDoc} */ + @Override + public EObject getSelectedModelElement() { + return getFirstElement(getSite().getSelectionProvider().getSelection()); + } + + /** {@inheritDoc} */ + @Override + public List<EObject> getSelectedModelElementList() { + return getEObjectElements(getSite().getSelectionProvider().getSelection()); + } + + /** Returns whether expert view is active. */ + public boolean isExpertViewActive() { + return INavigatorService.getInstance().isExpertViewActive(); + } + + /** Refreshes the viewer and reveals the given element. */ + public void refreshAndReveal(Object element) { + elementToBeRevealed = element; + refresh(); + } +}