Java tutorial
/* * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies). * All rights reserved. * This component and the accompanying materials are made available * under the terms of the License "Eclipse Public License v1.0" * which accompanies this distribution, and is available * at the URL "http://www.eclipse.org/legal/epl-v10.html". * * Initial Contributors: * Nokia Corporation - initial contribution. * * Contributors: * * Description: * */ package com.nokia.sdt.uidesigner.ui; import com.nokia.sdt.component.IComponent; import com.nokia.sdt.component.IComponentSet; import com.nokia.sdt.component.adapter.*; import com.nokia.sdt.datamodel.IDesignerDataModel; import com.nokia.sdt.datamodel.adapter.*; import com.nokia.sdt.datamodel.adapter.ComponentInstanceVisitor.Visitor; import com.nokia.sdt.displaymodel.adapter.IContainer; import com.nokia.sdt.editor.ICreationTool; import com.nokia.sdt.editor.IDesignerEditor; import com.nokia.sdt.uidesigner.derived.IExtendedFlyoutPreferences; import com.nokia.sdt.uidesigner.ui.command.CreationFactory; import com.nokia.sdt.uidesigner.ui.utils.*; import com.nokia.sdt.uimodel.UIModelPlugin; import com.nokia.cpp.internal.api.utils.core.*; import org.eclipse.core.runtime.*; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.gef.Tool; import org.eclipse.gef.palette.*; import org.eclipse.gef.ui.palette.FlyoutPaletteComposite; import org.eclipse.gef.ui.palette.FlyoutPaletteComposite.FlyoutPreferences; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.resource.ImageDescriptor; import java.util.*; public class PaletteFactory { public static class CreationTool extends org.eclipse.gef.tools.CreationTool { @Override protected boolean handleMove() { // This is overridden to reorder when the command is requested. // In order to support target feedback listeners, getting the command must follow // showing target feedback. This works correctly for moving and resizing, but not creating. // TODO: GEF people have been asked to reorder the calls in the CreationTool as below. // If they do so, we can remove this subclass as well as the call to setToolClass in the // constructor below. updateTargetRequest(); updateTargetUnderMouse(); showTargetFeedback(); setCurrentCommand(getCommand()); return true; } } public static class CreationToolEntry extends CombinedTemplateCreationEntry { private CreationToolEntry(String label, String shortDesc, Object template, CreationFactory factory, ImageDescriptor iconSmall, ImageDescriptor iconLarge) { super(label, shortDesc, template, factory, iconSmall, iconLarge); setToolClass(CreationTool.class); } private static IComponent getComponentFromEntry(CombinedTemplateCreationEntry entry) { Object template = entry.getTemplate(); if (template instanceof IAdaptable) return (IComponent) ((IAdaptable) template).getAdapter(IComponent.class); return null; } public boolean equals(Object obj) { if (obj instanceof CombinedTemplateCreationEntry) { IComponent component = getComponentFromEntry((CombinedTemplateCreationEntry) obj); IComponent componentSelf = getComponentFromEntry(this); if (component == componentSelf) return true; if (component == null || componentSelf == null || component.getId() == null || componentSelf.getId() == null) return getTemplate().equals(obj); return component.getId().equals(componentSelf.getId()); } return false; } } /** Default palette size. */ private static final int DEFAULT_PALETTE_SIZE = 125; /** Preference ID used to persist the palette location. */ private static final String PALETTE_DOCK_LOCATION = "PaletteFactory.Location"; //$NON-NLS-1$ /** Preference ID used to persist the palette size. */ private static final String PALETTE_SIZE = "PaletteFactory.Size"; //$NON-NLS-1$ /** Preference ID used to persist the flyout palette's state. */ private static final String PALETTE_STATE = "PaletteFactory.State"; //$NON-NLS-1$ /** Preference ID used to persist the flyout palette's info expanded state. */ private static final String PALETTE_INFO_EXPANDED = "PaletteFactory.InfoExpanded"; //$NON-NLS-1$ private static final String UNCATEGORIZED = Strings.getString("PaletteFactory.NoCategory"); //$NON-NLS-1$ /** * Return a FlyoutPreferences instance used to save/load the preferences of * a flyout palette. */ static FlyoutPreferences getCreatePalettePreferences() { // set default flyout palette preference values, in case the preference // store // does not hold stored values for the given preferences getPreferenceStore().setDefault(PALETTE_DOCK_LOCATION, -1); getPreferenceStore().setDefault(PALETTE_STATE, FlyoutPaletteComposite.STATE_PINNED_OPEN); getPreferenceStore().setDefault(PALETTE_SIZE, DEFAULT_PALETTE_SIZE); getPreferenceStore().setDefault(PALETTE_INFO_EXPANDED, true); return new IExtendedFlyoutPreferences() { public int getDockLocation() { return getPreferenceStore().getInt(PALETTE_DOCK_LOCATION); } public int getPaletteState() { return getPreferenceStore().getInt(PALETTE_STATE); } public int getPaletteWidth() { return getPreferenceStore().getInt(PALETTE_SIZE); } public boolean isInfoWidgetExpanded() { return getPreferenceStore().getBoolean(PALETTE_INFO_EXPANDED); } public void setDockLocation(int location) { getPreferenceStore().setValue(PALETTE_DOCK_LOCATION, location); } public void setPaletteState(int state) { getPreferenceStore().setValue(PALETTE_STATE, state); } public void setPaletteWidth(int width) { getPreferenceStore().setValue(PALETTE_SIZE, width); } public void setInfoWidgetExpanded(boolean state) { getPreferenceStore().setValue(PALETTE_INFO_EXPANDED, state); } }; } static class ComponentCreationTool implements ICreationTool { private IComponent component; public ComponentCreationTool(IComponent component) { this.component = component; } public EObject createNewObject(IDesignerDataModel dataModel) { return dataModel.createNewComponentInstance(component); } public String getCategory() { return component.getCategory(); } public String getDescription() { Object obj = component.getAdapter(IDocumentation.class); if (obj != null) { String text = ((IDocumentation) obj).getInformation(); return TextUtils.cleanUpXMLText(text); } return null; } public ImageDescriptor getIcon16() { Object obj = component.getAdapter(IDesignerImages.class); if (obj != null) { return ((IDesignerImages) obj).getSmallIconDescriptor(); } return null; } public ImageDescriptor getIcon24() { Object obj = component.getAdapter(IDesignerImages.class); if (obj != null) { return ((IDesignerImages) obj).getLargeIconDescriptor(); } return null; } public String getLabel() { return component.getFriendlyName(); } public Object getAdapter(Class adapter) { return component.getAdapter(adapter); } public void addNotify(EObject parent) { } } /** * Returns the preference store for the plugin. * * @see org.eclipse.ui.plugin.AbstractUIPlugin#getPreferenceStore() */ private static IPreferenceStore getPreferenceStore() { return UIModelPlugin.getDefault().getPreferenceStore(); } private static String getShortDescription(ICreationTool tool) { return tool.getDescription(); } private static ImageDescriptor getLargeIconDescriptor(ICreationTool tool) { ImageDescriptor imageDescriptor = tool.getIcon24(); if (imageDescriptor != null) return imageDescriptor; return ImageDescriptor.createFromImage(EditorUtils.getUnknownLargeIcon()); } private static ImageDescriptor getSmallIconDescriptor(ICreationTool tool) { ImageDescriptor imageDescriptor = tool.getIcon16(); if (imageDescriptor != null) return imageDescriptor; return ImageDescriptor.createFromImage(EditorUtils.getUnknownSmallIcon()); } private static String getCategory(ICreationTool tool) { return tool.getCategory(); } private static Set getDataModelContainers(IDesignerDataModel dataModel) { final Set containers = new HashSet(); ComponentInstanceVisitor.Visitor visitor = new ComponentInstanceVisitor.Visitor() { public Object visit(IComponentInstance ci) { IContainer container = Adapters.getContainer(ci.getEObject()); if (container != null) containers.add(container); return null; } }; ComponentInstanceVisitor.preOrderTraversal(dataModel.getRootContainers(), visitor); return containers; } /* * Allow each container in the model to veto the components in the component set * and return only those components allowed by those containers */ private static Set filterComponentsByContainersInModel(IDesignerDataModel model, IComponentSet cs, Set checkedContainers, boolean restrictive) { Set includedComponents = new HashSet(); Set containers = getDataModelContainers(model); // iterate the components first, so we can break when some container allows it for (Iterator componentIter = cs.iterator(); componentIter.hasNext();) { IComponent component = (IComponent) componentIter.next(); for (Iterator containerIter = containers.iterator(); containerIter.hasNext();) { IContainer container = (IContainer) containerIter.next(); IComponent containerComponent = Adapters.getComponent(container.getEObject()); checkedContainers.add(containerComponent.getId()); boolean allowedByContainer = restrictive ? container.canContainComponent(component, null) : container.isValidComponentInPalette(component); if (allowedByContainer) { includedComponents.add(component.getId()); break; } } } return includedComponents; } /* * Each of the included components can itself be a container and it may allow more components to be included. * Create a temporary model to instantiate the container components to get their IQueryContainment adapter. * Filter the component set by any containers found in the component set. */ private static Set filterByComponentContainers(IDesignerDataModel model, IComponentSet cs, Set includedComponents, Set checkedContainers) { // only test component that have not been included already Set testComponents = new HashSet(); for (Iterator iter = cs.iterator(); iter.hasNext();) { IComponent component = (IComponent) iter.next(); String componentId = component.getId(); if (!includedComponents.contains(componentId)) testComponents.add(componentId); } Set filteredComponents = null; try { IDesignerDataModel tempModel = model.getProvider().createCompatibleTemporary(model); filteredComponents = filterByComponentContainers(tempModel, cs, includedComponents, checkedContainers, testComponents); tempModel.dispose(); } catch (CoreException e) { String message = "PaletteFactory failed to create a temporary data model: "; //$NON-NLS-1$ IStatus status = Logging.newSimpleStatus(0, IStatus.ERROR, message + e.getMessage(), e); Logging.log(UIDesignerPlugin.getDefault(), status); } return filteredComponents; } private static boolean isContainerComponent(IComponent component) { IAttributes attributes = (IAttributes) component.getAdapter(IAttributes.class); return attributes.getBooleanAttribute(CommonAttributes.IS_LAYOUT_CONTAINER, false); } private static IQueryContainment getQueryContainmentAdapter(IDesignerDataModel model, IComponent component) { // create the container instance in the model EObject object = model.createRootContainerInstance(component); return (IQueryContainment) EcoreUtil.getRegisteredAdapter(object, IQueryContainment.class); } private static boolean isValidComponentInPalette(IComponent component) { IAttributes attributes = (IAttributes) component.getAdapter(IAttributes.class); return !component.isAbstract() && !attributes.getBooleanAttribute(CommonAttributes.NOT_IN_TOOLBOX, false); } private static Set setDifference(Set set1, Set set2) { Set difference = new HashSet(); difference.addAll(set1); difference.removeAll(set2); return difference; } /* * Use the data model to create instances of components that are containers and test the test components. */ private static Set filterByComponentContainers(IDesignerDataModel model, IComponentSet cs, Set includedComponents, Set checkedContainers, Set currentTestComponents) { // only test components that have not been included already Set testComponents = setDifference(currentTestComponents, includedComponents); // only check included components that have not been checked as containers already Set checkPotentialContainers = setDifference(includedComponents, checkedContainers); // for every container included, check if it will allow any of the test components for (Iterator iter = checkPotentialContainers.iterator(); iter.hasNext();) { String potentialContainerId = (String) iter.next(); IComponent potentialContainer = cs.lookupComponent(potentialContainerId); if (isContainerComponent(potentialContainer)) { checkedContainers.add(potentialContainerId); IQueryContainment queryContainment = getQueryContainmentAdapter(model, potentialContainer); if (queryContainment == null) continue; // for every test component, if valid, add to the included set // if valid component is a container, add for (Iterator testIter = testComponents.iterator(); testIter.hasNext();) { String componentId = (String) testIter.next(); IComponent component = cs.lookupComponent(componentId); if (queryContainment.isValidComponentInPalette(component)) { if (!includedComponents.contains(componentId)) { includedComponents.add(componentId); includedComponents.addAll(filterByComponentContainers(model, cs, includedComponents, checkedContainers, testComponents)); } } } } } return includedComponents; } /** * Creates the PaletteRoot and adds all palette elements. Use this factory * method to create a new palette for your graphical editor. * * @return a new PaletteRoot */ public static PaletteRoot createPalette(IDesignerEditor editor, List<String> openDrawerNames, boolean closeDrawers, boolean restrictive) { PaletteRoot palette = new PaletteRoot(); palette.add(createToolsGroupAndDefaultEntry(palette, editor)); IDesignerDataModel dataModel = editor.getDataModel(); if (dataModel == null) return palette; IComponentSet cs = dataModel.getComponentSet(); // for (IComponent component : cs) { // System.out.println(component.toString()); // } Set checkedContainers = new HashSet(); Set includedComponentIds = filterComponentsByContainersInModel(dataModel, cs, checkedContainers, restrictive); if (!restrictive) includedComponentIds = filterByComponentContainers(dataModel, cs, includedComponentIds, checkedContainers); Set<ICreationTool> includedCreationTools = new HashSet(); for (Iterator iter = includedComponentIds.iterator(); iter.hasNext();) { IComponent component = cs.lookupComponent((String) iter.next()); if (isValidComponentInPalette(component)) { includedCreationTools.add(new ComponentCreationTool(component)); } } includedCreationTools.addAll(getCreationToolsFromProviders(dataModel, editor)); // organize the tools into a category->List<ICreationTool> map SortedMap<String, List<ICreationTool>> toolMap = new TreeMap(); for (Iterator<ICreationTool> iter = includedCreationTools.iterator(); iter.hasNext();) { ICreationTool tool = iter.next(); String category = getCategory(tool); if (category == null) category = UNCATEGORIZED; if (!toolMap.containsKey(category)) { List<ICreationTool> toolList = new ArrayList(); toolMap.put(category, toolList); } List<ICreationTool> toolList = toolMap.get(category); toolList.add(tool); } if (openDrawerNames == null) openDrawerNames = getContainerOpenDrawers(dataModel); // add drawers and entries for (Iterator<String> categoryIterator = toolMap.keySet().iterator(); categoryIterator.hasNext();) { String category = categoryIterator.next(); PaletteDrawer drawer = new PaletteDrawer(category); boolean keepOpen = (openDrawerNames != null) && openDrawerNames.contains(category); if (closeDrawers && !keepOpen) drawer.setInitialState(PaletteDrawer.INITIAL_STATE_CLOSED); List<ICreationTool> toolList = toolMap.get(category); Collections.sort(toolList, new Comparator<ICreationTool>() { public int compare(ICreationTool t1, ICreationTool t2) { String name1 = (t1 == null ? null : t1.getLabel()); String name2 = (t2 == null ? null : t2.getLabel()); if (name1 == null && name2 == null) return 0; if (name1 == null) return 1; if (name2 == null) return -1; return name1.compareTo(name2); } }); for (Iterator<ICreationTool> iter = toolList.iterator(); iter.hasNext();) { ICreationTool tool = iter.next(); CombinedTemplateCreationEntry entry = new CreationToolEntry(getLabel(tool), getShortDescription(tool), tool, new CreationFactory(tool), getSmallIconDescriptor(tool), getLargeIconDescriptor(tool)); drawer.add(entry); } palette.add(drawer); } return palette; } private static Collection<ICreationTool> getCreationToolsFromProviders(IDesignerDataModel dataModel, final IDesignerEditor editor) { final Collection<ICreationTool> tools = new ArrayList(); ComponentInstanceVisitor.preOrderTraversal(dataModel.getRootContainers(), new Visitor() { public Object visit(IComponentInstance ci) { ICreationToolProvider provider = Adapters.getCreationToolProvider(ci.getEObject()); if (provider != null) tools.addAll(provider.getCreationTools(editor)); return null; } }); return tools; } private static List<String> getContainerOpenDrawers(IDesignerDataModel dataModel) { List<String> allOpenDrawers = new ArrayList(); Set dataModelContainers = getDataModelContainers(dataModel); for (Iterator<IContainer> iter = dataModelContainers.iterator(); iter.hasNext();) { IAttributes attributes = Adapters.getAttributes(iter.next().getEObject()); String attribute = attributes.getAttribute(CommonAttributes.ASSOCIATED_PALETTE_DRAWER); if (attribute != null) { IComponent component = attributes.getComponent(); String categoryText = component.getProvider().getCategoryText(attribute); allOpenDrawers.add(categoryText); } } return allOpenDrawers; } private static String getLabel(ICreationTool tool) { return tool.getLabel(); } /** Create the "Tools" group. */ private static PaletteContainer createToolsGroupAndDefaultEntry(PaletteRoot palette, final IDesignerEditor editor) { PaletteGroup toolGroup = new PaletteGroup(Strings.getString("PaletteFactory.ToolsGroupName")); //$NON-NLS-1$ // Add a selection tool to the group ToolEntry tool = new SelectionToolEntry() { private Tool selectionTool; /* (non-Javadoc) * @see org.eclipse.gef.palette.SelectionToolEntry#createTool() */ public Tool createTool() { if (selectionTool == null) { selectionTool = new ViewEditorSelectionTool(editor); editor.getEditDomain().setDefaultTool(selectionTool); } return selectionTool; } }; toolGroup.add(tool); palette.setDefaultEntry(tool); // Add a marquee tool to the group toolGroup.add(new MarqueeToolEntry(Strings.getString("PaletteFactory.MarqueeToolLabel"), //$NON-NLS-1$ Strings.getString("PaletteFactory.MarqueeToolDesc"))); //$NON-NLS-1$ // Add a (unnamed) separator to the group toolGroup.add(new PaletteSeparator()); return toolGroup; } }