1 /******************************************************************************* 2 * Copyright (c) 2010, 2018 BestSolution.at and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation 13 * Wim Jongman <wim.jongman@remainsoftware.com> - Maintenance 14 * Marco Descher <marco@descher.at> - Bug395982, 426653, 422465, 429674 15 * Lars Vogel <Lars.Vogel@gmail.com> - Ongoing maintenance 16 * Steven Spungin <steven@spungin.tv> - Bug 396902, 431755, 431735, 424730, 424730, 391089, 437236, 437552, Ongoing 17 * Maintenance 18 * Simon Scholz <simon.scholz@vogella.com> - Bug 475365 19 * Olivier Prouvost <olivier.prouvost@opcoach.com> - Bug 472706, 429684, 531451 20 * Dmitry Spiridenok <d.spiridenok@gmail.com> - Bug 429684 21 ******************************************************************************/ 22 package org.eclipse.e4.tools.emf.ui.internal.common; 23 24 import java.util.ArrayList; 25 import java.util.Arrays; 26 import java.util.Collection; 27 import java.util.HashMap; 28 import java.util.Iterator; 29 import java.util.List; 30 import java.util.Map; 31 import java.util.Objects; 32 33 import javax.annotation.PostConstruct; 34 import javax.annotation.PreDestroy; 35 import javax.inject.Inject; 36 import javax.inject.Named; 37 38 import org.eclipse.core.databinding.ObservablesManager; 39 import org.eclipse.core.databinding.observable.list.IObservableList; 40 import org.eclipse.core.databinding.observable.list.WritableList; 41 import org.eclipse.core.databinding.observable.map.IObservableMap; 42 import org.eclipse.core.databinding.observable.masterdetail.IObservableFactory; 43 import org.eclipse.core.databinding.observable.set.WritableSet; 44 import org.eclipse.core.databinding.property.list.IListProperty; 45 import org.eclipse.core.resources.IProject; 46 import org.eclipse.core.runtime.CoreException; 47 import org.eclipse.core.runtime.IConfigurationElement; 48 import org.eclipse.core.runtime.IExtensionPoint; 49 import org.eclipse.core.runtime.IExtensionRegistry; 50 import org.eclipse.core.runtime.IProgressMonitor; 51 import org.eclipse.core.runtime.RegistryFactory; 52 import org.eclipse.core.runtime.preferences.IEclipsePreferences; 53 import org.eclipse.e4.core.contexts.ContextInjectionFactory; 54 import org.eclipse.e4.core.contexts.IEclipseContext; 55 import org.eclipse.e4.core.di.annotations.Execute; 56 import org.eclipse.e4.core.di.annotations.Optional; 57 import org.eclipse.e4.core.di.extensions.Preference; 58 import org.eclipse.e4.core.services.contributions.IContributionFactory; 59 import org.eclipse.e4.core.services.log.Logger; 60 import org.eclipse.e4.core.services.nls.Translation; 61 import org.eclipse.e4.core.services.translation.TranslationService; 62 import org.eclipse.e4.tools.emf.ui.common.AbstractElementEditorContribution; 63 import org.eclipse.e4.tools.emf.ui.common.IContributionClassCreator; 64 import org.eclipse.e4.tools.emf.ui.common.IEditorDescriptor; 65 import org.eclipse.e4.tools.emf.ui.common.IEditorFeature; 66 import org.eclipse.e4.tools.emf.ui.common.IEditorFeature.FeatureClass; 67 import org.eclipse.e4.tools.emf.ui.common.IExtensionLookup; 68 import org.eclipse.e4.tools.emf.ui.common.IModelExtractor; 69 import org.eclipse.e4.tools.emf.ui.common.IModelResource; 70 import org.eclipse.e4.tools.emf.ui.common.IScriptingSupport; 71 import org.eclipse.e4.tools.emf.ui.common.MemoryTransfer; 72 import org.eclipse.e4.tools.emf.ui.common.ModelEditorPreferences; 73 import org.eclipse.e4.tools.emf.ui.common.Plugin; 74 import org.eclipse.e4.tools.emf.ui.common.Util; 75 import org.eclipse.e4.tools.emf.ui.common.component.AbstractComponentEditor; 76 import org.eclipse.e4.tools.emf.ui.internal.Messages; 77 import org.eclipse.e4.tools.emf.ui.internal.ResourceProvider; 78 import org.eclipse.e4.tools.emf.ui.internal.common.component.AddonsEditor; 79 import org.eclipse.e4.tools.emf.ui.internal.common.component.ApplicationEditor; 80 import org.eclipse.e4.tools.emf.ui.internal.common.component.AreaEditor; 81 import org.eclipse.e4.tools.emf.ui.internal.common.component.BindingContextEditor; 82 import org.eclipse.e4.tools.emf.ui.internal.common.component.BindingTableEditor; 83 import org.eclipse.e4.tools.emf.ui.internal.common.component.CategoryEditor; 84 import org.eclipse.e4.tools.emf.ui.internal.common.component.CommandEditor; 85 import org.eclipse.e4.tools.emf.ui.internal.common.component.CommandParameterEditor; 86 import org.eclipse.e4.tools.emf.ui.internal.common.component.CompositePartEditor; 87 import org.eclipse.e4.tools.emf.ui.internal.common.component.CoreExpressionEditor; 88 import org.eclipse.e4.tools.emf.ui.internal.common.component.DefaultEditor; 89 import org.eclipse.e4.tools.emf.ui.internal.common.component.DirectMenuItemEditor; 90 import org.eclipse.e4.tools.emf.ui.internal.common.component.DirectToolItemEditor; 91 import org.eclipse.e4.tools.emf.ui.internal.common.component.DynamicMenuContributionEditor; 92 import org.eclipse.e4.tools.emf.ui.internal.common.component.HandledMenuItemEditor; 93 import org.eclipse.e4.tools.emf.ui.internal.common.component.HandledToolItemEditor; 94 import org.eclipse.e4.tools.emf.ui.internal.common.component.HandlerEditor; 95 import org.eclipse.e4.tools.emf.ui.internal.common.component.ImperativeExpressionEditor; 96 import org.eclipse.e4.tools.emf.ui.internal.common.component.KeyBindingEditor; 97 import org.eclipse.e4.tools.emf.ui.internal.common.component.MenuContributionEditor; 98 import org.eclipse.e4.tools.emf.ui.internal.common.component.MenuEditor; 99 import org.eclipse.e4.tools.emf.ui.internal.common.component.MenuSeparatorEditor; 100 import org.eclipse.e4.tools.emf.ui.internal.common.component.ModelFragmentsEditor; 101 import org.eclipse.e4.tools.emf.ui.internal.common.component.ParameterEditor; 102 import org.eclipse.e4.tools.emf.ui.internal.common.component.PartDescriptorEditor; 103 import org.eclipse.e4.tools.emf.ui.internal.common.component.PartEditor; 104 import org.eclipse.e4.tools.emf.ui.internal.common.component.PartSashContainerEditor; 105 import org.eclipse.e4.tools.emf.ui.internal.common.component.PartStackEditor; 106 import org.eclipse.e4.tools.emf.ui.internal.common.component.PerspectiveEditor; 107 import org.eclipse.e4.tools.emf.ui.internal.common.component.PerspectiveStackEditor; 108 import org.eclipse.e4.tools.emf.ui.internal.common.component.PlaceholderEditor; 109 import org.eclipse.e4.tools.emf.ui.internal.common.component.PopupMenuEditor; 110 import org.eclipse.e4.tools.emf.ui.internal.common.component.StringModelFragment; 111 import org.eclipse.e4.tools.emf.ui.internal.common.component.ToolBarContributionEditor; 112 import org.eclipse.e4.tools.emf.ui.internal.common.component.ToolBarEditor; 113 import org.eclipse.e4.tools.emf.ui.internal.common.component.ToolBarSeparatorEditor; 114 import org.eclipse.e4.tools.emf.ui.internal.common.component.ToolControlEditor; 115 import org.eclipse.e4.tools.emf.ui.internal.common.component.TrimBarEditor; 116 import org.eclipse.e4.tools.emf.ui.internal.common.component.TrimContributionEditor; 117 import org.eclipse.e4.tools.emf.ui.internal.common.component.TrimmedWindowEditor; 118 import org.eclipse.e4.tools.emf.ui.internal.common.component.WindowEditor; 119 import org.eclipse.e4.tools.emf.ui.internal.common.component.tabs.EmfUtil; 120 import org.eclipse.e4.tools.emf.ui.internal.common.component.tabs.IGotoObject; 121 import org.eclipse.e4.tools.emf.ui.internal.common.component.tabs.ListTab; 122 import org.eclipse.e4.tools.emf.ui.internal.common.component.tabs.XmiTab; 123 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VApplicationAddons; 124 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VApplicationCategoriesEditor; 125 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VApplicationWindowEditor; 126 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VBindingTableEditor; 127 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VCommandEditor; 128 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VControlsEditor; 129 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VHandlerEditor; 130 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VItemParametersEditor; 131 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VMenuContributionsEditor; 132 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VModelFragmentsEditor; 133 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VModelImportsEditor; 134 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPartDescriptor; 135 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPartDescriptorMenuEditor; 136 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPartDescriptorTrimEditor; 137 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPartMenuEditor; 138 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPartTrimEditor; 139 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPerspectiveControlEditor; 140 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPerspectiveTrimEditor; 141 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VPerspectiveWindowsEditor; 142 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VRootBindingContexts; 143 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VSnippetsEditor; 144 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VToolBarContributionsEditor; 145 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VTrimContributionsEditor; 146 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VWindowControlEditor; 147 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VWindowSharedElementsEditor; 148 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VWindowTrimEditor; 149 import org.eclipse.e4.tools.emf.ui.internal.common.component.virtual.VWindowWindowsEditor; 150 import org.eclipse.e4.tools.emf.ui.internal.common.properties.ExportIdsHandler; 151 import org.eclipse.e4.tools.emf.ui.internal.common.properties.ExternalizeStringHandler; 152 import org.eclipse.e4.tools.emf.ui.internal.common.properties.ProjectOSGiTranslationProvider; 153 import org.eclipse.e4.tools.emf.ui.internal.common.xml.EMFDocumentResourceMediator; 154 import org.eclipse.e4.tools.services.IClipboardService; 155 import org.eclipse.e4.tools.services.IClipboardService.Handler; 156 import org.eclipse.e4.tools.services.IResourcePool; 157 import org.eclipse.e4.ui.di.Focus; 158 import org.eclipse.e4.ui.di.Persist; 159 import org.eclipse.e4.ui.di.PersistState; 160 import org.eclipse.e4.ui.di.UIEventTopic; 161 import org.eclipse.e4.ui.dialogs.filteredtree.FilteredTree; 162 import org.eclipse.e4.ui.dialogs.filteredtree.PatternFilter; 163 import org.eclipse.e4.ui.model.application.MApplication; 164 import org.eclipse.e4.ui.model.application.MApplicationElement; 165 import org.eclipse.e4.ui.model.application.commands.impl.CommandsPackageImpl; 166 import org.eclipse.e4.ui.model.application.impl.ApplicationElementImpl; 167 import org.eclipse.e4.ui.model.application.impl.ApplicationPackageImpl; 168 import org.eclipse.e4.ui.model.application.ui.MContext; 169 import org.eclipse.e4.ui.model.application.ui.MElementContainer; 170 import org.eclipse.e4.ui.model.application.ui.MUIElement; 171 import org.eclipse.e4.ui.model.application.ui.MUILabel; 172 import org.eclipse.e4.ui.model.application.ui.advanced.impl.AdvancedPackageImpl; 173 import org.eclipse.e4.ui.model.application.ui.basic.MPart; 174 import org.eclipse.e4.ui.model.application.ui.basic.impl.BasicPackageImpl; 175 import org.eclipse.e4.ui.model.application.ui.impl.UiPackageImpl; 176 import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuPackageImpl; 177 import org.eclipse.e4.ui.model.fragment.MModelFragment; 178 import org.eclipse.e4.ui.model.fragment.MModelFragments; 179 import org.eclipse.e4.ui.model.fragment.MStringModelFragment; 180 import org.eclipse.e4.ui.model.fragment.impl.FragmentPackageImpl; 181 import org.eclipse.e4.ui.model.internal.ModelUtils; 182 import org.eclipse.e4.ui.services.IServiceConstants; 183 import org.eclipse.e4.ui.workbench.UIEvents; 184 import org.eclipse.e4.ui.workbench.UIEvents.EventTags; 185 import org.eclipse.e4.ui.workbench.modeling.ESelectionService; 186 import org.eclipse.emf.common.command.AbstractCommand; 187 import org.eclipse.emf.common.command.Command; 188 import org.eclipse.emf.common.command.CompoundCommand; 189 import org.eclipse.emf.databinding.EMFProperties; 190 import org.eclipse.emf.databinding.FeaturePath; 191 import org.eclipse.emf.databinding.IEMFProperty; 192 import org.eclipse.emf.ecore.EClass; 193 import org.eclipse.emf.ecore.EClassifier; 194 import org.eclipse.emf.ecore.EObject; 195 import org.eclipse.emf.ecore.EStructuralFeature; 196 import org.eclipse.emf.ecore.util.EcoreUtil; 197 import org.eclipse.emf.edit.command.AddCommand; 198 import org.eclipse.emf.edit.command.CommandParameter; 199 import org.eclipse.emf.edit.command.DeleteCommand; 200 import org.eclipse.emf.edit.command.MoveCommand; 201 import org.eclipse.emf.edit.command.RemoveCommand; 202 import org.eclipse.emf.edit.domain.EditingDomain; 203 import org.eclipse.jface.action.Action; 204 import org.eclipse.jface.action.MenuManager; 205 import org.eclipse.jface.action.Separator; 206 import org.eclipse.jface.databinding.viewers.ObservableListTreeContentProvider; 207 import org.eclipse.jface.databinding.viewers.TreeStructureAdvisor; 208 import org.eclipse.jface.dialogs.MessageDialog; 209 import org.eclipse.jface.resource.FontDescriptor; 210 import org.eclipse.jface.resource.ImageDescriptor; 211 import org.eclipse.jface.resource.ImageRegistry; 212 import org.eclipse.jface.resource.JFaceResources; 213 import org.eclipse.jface.resource.StringConverter; 214 import org.eclipse.jface.viewers.AbstractTreeViewer; 215 import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider; 216 import org.eclipse.jface.viewers.IStructuredSelection; 217 import org.eclipse.jface.viewers.ITreeViewerListener; 218 import org.eclipse.jface.viewers.StructuredSelection; 219 import org.eclipse.jface.viewers.TreeExpansionEvent; 220 import org.eclipse.jface.viewers.TreeViewer; 221 import org.eclipse.jface.viewers.Viewer; 222 import org.eclipse.jface.viewers.ViewerDropAdapter; 223 import org.eclipse.swt.SWT; 224 import org.eclipse.swt.custom.CTabFolder; 225 import org.eclipse.swt.custom.CTabItem; 226 import org.eclipse.swt.custom.SashForm; 227 import org.eclipse.swt.custom.StackLayout; 228 import org.eclipse.swt.dnd.Clipboard; 229 import org.eclipse.swt.dnd.DND; 230 import org.eclipse.swt.dnd.DragSourceAdapter; 231 import org.eclipse.swt.dnd.DragSourceEvent; 232 import org.eclipse.swt.dnd.Transfer; 233 import org.eclipse.swt.dnd.TransferData; 234 import org.eclipse.swt.events.KeyAdapter; 235 import org.eclipse.swt.events.KeyEvent; 236 import org.eclipse.swt.events.KeyListener; 237 import org.eclipse.swt.events.SelectionAdapter; 238 import org.eclipse.swt.events.SelectionEvent; 239 import org.eclipse.swt.events.TreeAdapter; 240 import org.eclipse.swt.events.TreeEvent; 241 import org.eclipse.swt.graphics.RGB; 242 import org.eclipse.swt.layout.FillLayout; 243 import org.eclipse.swt.layout.GridData; 244 import org.eclipse.swt.widgets.Composite; 245 import org.eclipse.swt.widgets.Control; 246 import org.eclipse.swt.widgets.Display; 247 import org.eclipse.swt.widgets.Listener; 248 import org.eclipse.swt.widgets.TreeItem; 249 import org.eclipse.ui.forms.widgets.FormToolkit; 250 import org.eclipse.ui.forms.widgets.Section; 251 252 public class ModelEditor implements IGotoObject { 253 private static final String ORG_ECLIPSE_E4_TOOLS_MODELEDITOR_FILTEREDTREE_ENABLED_XMITAB_DISABLED = "org.eclipse.e4.tools.modeleditor.filteredtree.enabled.xmitab.disabled";//$NON-NLS-1$ 254 255 public static final String CSS_CLASS_KEY = "org.eclipse.e4.ui.css.CssClassName"; //$NON-NLS-1$ 256 257 public static final String VIRTUAL_PART_MENU = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PART_MENU"; //$NON-NLS-1$ 258 public static final String VIRTUAL_HANDLER = "org.eclipse.e4.tools.emf.ui.VIRTUAL_HANDLER"; //$NON-NLS-1$ 259 public static final String VIRTUAL_CONTROLS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_CONTROLS"; //$NON-NLS-1$ 260 public static final String VIRTUAL_BINDING_TABLE = "org.eclipse.e4.tools.emf.ui.VIRTUAL_BINDING_TABLE"; //$NON-NLS-1$ 261 public static final String VIRTUAL_COMMAND = "org.eclipse.e4.tools.emf.ui.VIRTUAL_COMMAND"; //$NON-NLS-1$ 262 public static final String VIRTUAL_APPLICATION_WINDOWS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_APPLICATION_WINDOWS"; //$NON-NLS-1$ 263 public static final String VIRTUAL_PERSPECTIVE_WINDOWS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PERSPECTIVE_WINDOWS"; //$NON-NLS-1$ 264 public static final String VIRTUAL_WINDOW_WINDOWS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_WINDOW_WINDOWS"; //$NON-NLS-1$ 265 public static final String VIRTUAL_WINDOW_CONTROLS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_WINDOW_CONTROLS"; //$NON-NLS-1$ 266 public static final String VIRTUAL_PART_TRIMS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PART_TRIMS"; //$NON-NLS-1$ 267 public static final String VIRTUAL_PART_DESCRIPTORS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PART_DESCRIPTORS"; //$NON-NLS-1$ 268 public static final String VIRTUAL_PARTDESCRIPTOR_MENU = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PARTDESCRIPTOR_MENU"; //$NON-NLS-1$ 269 public static final String VIRTUAL_PARTDESCRIPTOR_TRIMS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PART_DESCRIPTOR_TRIMS"; //$NON-NLS-1$ 270 public static final String VIRTUAL_TRIMMED_WINDOW_TRIMS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_TRIMMED_WINDOW_TRIMS"; //$NON-NLS-1$ 271 public static final String VIRTUAL_ADDONS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_ADDONS"; //$NON-NLS-1$ 272 public static final String VIRTUAL_MENU_CONTRIBUTIONS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_MENU_CONTRIBUTIONS"; //$NON-NLS-1$ 273 public static final String VIRTUAL_TOOLBAR_CONTRIBUTIONS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_TOOLBAR_CONTRIBUTIONS"; //$NON-NLS-1$ 274 public static final String VIRTUAL_TRIM_CONTRIBUTIONS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_TRIM_CONTRIBUTIONS"; //$NON-NLS-1$ 275 public static final String VIRTUAL_WINDOW_SHARED_ELEMENTS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_WINDOW_SHARED_ELEMENTS"; //$NON-NLS-1$ 276 public static final String VIRTUAL_WINDOW_SNIPPETS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_WINDOW_SNIPPETS"; //$NON-NLS-1$ 277 278 public static final String VIRTUAL_MODEL_FRAGEMENTS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_MODEL_FRAGEMENTS"; //$NON-NLS-1$ 279 public static final String VIRTUAL_MODEL_IMPORTS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_MODEL_IMPORTS"; //$NON-NLS-1$ 280 public static final String VIRTUAL_CATEGORIES = "org.eclipse.e4.tools.emf.ui.VIRTUAL_CATEGORIES"; //$NON-NLS-1$ 281 public static final String VIRTUAL_PARAMETERS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PARAMETERS"; //$NON-NLS-1$ 282 public static final String VIRTUAL_MENUELEMENTS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_MENUELEMENTS"; //$NON-NLS-1$ 283 public static final String VIRTUAL_ROOT_CONTEXTS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_ROOT_CONTEXTS"; //$NON-NLS-1$ 284 public static final String VIRTUAL_PERSPECTIVE_CONTROLS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PERSPECTIVE_CONTROLS"; //$NON-NLS-1$ 285 public static final String VIRTUAL_PERSPECTIVE_TRIMS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_PERSPECTIVE_TRIMS"; //$NON-NLS-1$ 286 public static final String VIRTUAL_SNIPPETS = "org.eclipse.e4.tools.emf.ui.VIRTUAL_SNIPPETS"; //$NON-NLS-1$ 287 288 public static final int TAB_FORM = 0; 289 public static final int TAB_XMI = 1; 290 public static final int TAB_LIST = 2; 291 292 293 294 /** 295 * A map with key = eClass name or virtual key, value is an 296 * AbstractComponentEditor instance This map is filled on the fly when getting 297 * editors 298 */ 299 private final Map<String, AbstractComponentEditor<?>> editors = new HashMap<>(); 300 301 /** 302 * A map with key = eClass name or virtual key, value is a class of 303 * AbstractComponentEditor. This map is filled on init by registerEditor 304 */ 305 private final Map<String, Class<? extends AbstractComponentEditor<?>>> editorsClasses = new HashMap<>(); 306 307 private final Map<Class<?>, List<AbstractElementEditorContribution>> tabContributions = new HashMap<>(); 308 private final List<FeaturePath> labelFeaturePaths = new ArrayList<>(); 309 private final List<IEditorFeature> editorFeatures = new ArrayList<>(); 310 private final List<IContributionClassCreator> contributionCreator = new ArrayList<>(); 311 312 private TreeViewer viewer; 313 private final IModelResource modelProvider; 314 private final IProject project; 315 316 /** An imageRegistry for dynamic component images (see bug #403583) */ 317 private final ImageRegistry componentImages = new ImageRegistry(); 318 319 @Inject 320 ESelectionService selectionService; 321 322 @Inject 323 MApplication app; 324 325 private final IEclipseContext context; 326 private boolean fragment; 327 private Handler clipboardHandler; 328 329 @Inject 330 @Optional 331 private IClipboardService clipboardService; 332 333 @Inject 334 @Preference(nodePath = Plugin.ID, value = ModelEditorPreferences.AUTO_CREATE_ELEMENT_ID) 335 private boolean autoCreateElementId; 336 337 @Inject 338 @Preference(nodePath = Plugin.ID, value = ModelEditorPreferences.SHOW_XMI_ID) 339 private boolean showXMIId; 340 341 @Inject 342 @Preference(nodePath = Plugin.ID) 343 IEclipsePreferences preferences; 344 345 @Inject 346 @Optional 347 private IExtensionLookup extensionLookup; 348 349 @Inject 350 @Translation 351 private Messages messages; 352 353 @Inject 354 @Optional 355 private IModelExtractor modelExtractor; 356 357 @Inject 358 @Optional 359 MPart currentPart; 360 361 @Inject 362 private Logger logger; 363 364 private final ObservablesManager obsManager; 365 366 private final IResourcePool resourcePool; 367 368 private EMFDocumentResourceMediator emfDocumentProvider; 369 370 private AbstractComponentEditor<?> currentEditor; 371 372 private Listener keyListener; 373 374 private CTabFolder editorTabFolder; 375 376 private boolean mod1Down = false; 377 378 private boolean saving; 379 380 private ListTab listTab; 381 382 private CTabItem tabItemXmi; 383 384 private CTabItem tabItemList; 385 386 private CTabItem tabItemTree; 387 388 private XmiTab xmiTab; 389 390 private Section headerContainer; 391 ModelEditor(Composite composite, IEclipseContext context, IModelResource modelProvider, IProject project, final IResourcePool resourcePool)392 public ModelEditor(Composite composite, IEclipseContext context, IModelResource modelProvider, IProject project, 393 final IResourcePool resourcePool) { 394 this.resourcePool = resourcePool; 395 this.modelProvider = modelProvider; 396 this.project = project; 397 this.context = context; 398 this.context.set(ModelEditor.class, this); 399 obsManager = new ObservablesManager(); 400 if (project != null) { 401 String localeString = ""; //$NON-NLS-1$ 402 final Object object = this.context.get(TranslationService.LOCALE); 403 // TODO simplify once we break e4 tools 404 // compatibility with Luna, in Luna we representation has changed to 405 // be Locale instead of String 406 if (object != null) { 407 localeString = object.toString(); 408 } 409 final ProjectOSGiTranslationProvider translationProvider = new ProjectOSGiTranslationProvider(project, 410 localeString) { 411 @Override 412 protected void updateResourceBundle() { 413 super.updateResourceBundle(); 414 if (viewer != null) { 415 viewer.getControl().getDisplay().asyncExec(() -> viewer.refresh()); 416 } 417 } 418 }; 419 context.set(ProjectOSGiTranslationProvider.class, translationProvider); 420 } 421 labelFeaturePaths.add(FeaturePath.fromList(UiPackageImpl.Literals.UI_ELEMENT__TO_BE_RENDERED)); 422 labelFeaturePaths.add(FeaturePath.fromList(UiPackageImpl.Literals.UI_ELEMENT__VISIBLE)); 423 424 // This is a workaround until Bug 437207 is merged. 425 // @PersistState will not be invoked. 426 composite.addDisposeListener(arg0 -> persistState()); 427 } 428 429 @PersistState persistState()430 protected void persistState() { 431 if (listTab != null) { 432 listTab.saveSettings(); 433 } 434 } 435 436 @PostConstruct postCreate(Composite composite)437 void postCreate(Composite composite) { 438 if (project == null) { 439 keyListener = event -> { 440 if ((event.stateMask & SWT.ALT) == SWT.ALT) { 441 findAndHighlight(context.get(Display.class).getFocusControl()); 442 } 443 }; 444 context.get(Display.class).addFilter(SWT.MouseUp, keyListener); 445 } 446 447 context.set(ModelEditor.class, this); 448 context.set(IResourcePool.class, resourcePool); 449 context.set(EditingDomain.class, modelProvider.getEditingDomain()); 450 context.set(IModelResource.class, modelProvider); 451 452 if (project != null) { 453 context.set(IProject.class, project); 454 } 455 456 loadEditorFeatures(); 457 registerDefaultEditors(); 458 registerVirtualEditors(); 459 460 registerContributedEditors(); 461 registerContributedVirtualEditors(); 462 registerContributedEditorTabs(); 463 loadContributionCreators(); 464 465 fragment = modelProvider.getRoot().get(0) instanceof MModelFragments; 466 467 // For Bug 396902, create this before creating the Form tab 468 emfDocumentProvider = new EMFDocumentResourceMediator(modelProvider); 469 470 editorTabFolder = new CTabFolder(composite, SWT.BOTTOM); 471 tabItemTree = new CTabItem(editorTabFolder, SWT.NONE); 472 tabItemTree.setText(messages.ModelEditor_Form); 473 tabItemTree.setControl(createFormTab(editorTabFolder)); 474 tabItemTree.setImage(resourcePool.getImageUnchecked(ResourceProvider.IMG_Obj16_application_form)); 475 476 tabListShow(true); 477 478 tabItemXmi = new CTabItem(editorTabFolder, SWT.NONE); 479 tabItemXmi.setText(messages.ModelEditor_XMI); 480 xmiTab = createXMITab(editorTabFolder); 481 tabItemXmi.setControl(xmiTab); 482 tabItemXmi.setImage(resourcePool.getImageUnchecked(ResourceProvider.IMG_Obj16_chart_organisation)); 483 editorTabFolder.addSelectionListener(new SelectionAdapter() { 484 @Override 485 public void widgetSelected(SelectionEvent e) { 486 if (editorTabFolder.getSelectionIndex() == getTabIndex(tabItemXmi)) { 487 emfDocumentProvider.updateFromEMF(); 488 } 489 } 490 }); 491 492 editorTabFolder.addSelectionListener(new SelectionAdapter() { 493 @Override 494 public void widgetSelected(SelectionEvent e) { 495 // When the list tab is visible, register the IViewEObjects 496 // interface 497 // This allows external commands to interact with the view. 498 // Eventually, all 3 tabs, or even the ModelEditor itself, could 499 // implement the interface. 500 final String key = "org.eclipse.e4.tools.active-object-viewer"; //$NON-NLS-1$ 501 if (listTab != null && editorTabFolder.getSelectionIndex() == getTabIndex(listTab.getTabItem())) { 502 app.getContext().set(key, listTab); 503 } else { 504 app.getContext().set(key, null); 505 } 506 } 507 }); 508 509 editorTabFolder.setSelection(0); 510 } 511 512 /** 513 * @param tabItem 514 * @return The index of the tab item. Should never return -1. 515 */ getTabIndex(CTabItem tabItem)516 static public int getTabIndex(CTabItem tabItem) { 517 return Arrays.asList(tabItem.getParent().getItems()).indexOf(tabItem); 518 } 519 findAndHighlight(Control control)520 private void findAndHighlight(Control control) { 521 if (control != null) { 522 MApplicationElement m = findModelElement(control); 523 final MApplicationElement o = m; 524 if (m != null) { 525 final List<MApplicationElement> l = new ArrayList<>(); 526 do { 527 l.add(m); 528 m = (MApplicationElement) ((EObject) m).eContainer(); 529 } while (m != null); 530 531 if (o instanceof MPart) { 532 System.err.println(getClass().getName() + ".findAndHighLight: " + o); //$NON-NLS-1$ 533 System.err 534 .println(getClass().getName() + ".findAndHighLight: " + ((EObject) o).eContainingFeature()); //$NON-NLS-1$ 535 } 536 537 viewer.setSelection(new StructuredSelection(o)); 538 } 539 } 540 } 541 findModelElement(Control control)542 private MApplicationElement findModelElement(Control control) { 543 do { 544 if (control.getData("modelElement") != null) { //$NON-NLS-1$ 545 return (MApplicationElement) control.getData("modelElement"); //$NON-NLS-1$ 546 } 547 control = control.getParent(); 548 } while (control != null); 549 550 return null; 551 } 552 createXMITab(Composite composite)553 private XmiTab createXMITab(Composite composite) { 554 final IEclipseContext childContext = context.createChild(); 555 childContext.set(Composite.class, composite); 556 childContext.set(EMFDocumentResourceMediator.class, emfDocumentProvider); 557 childContext.set(IEclipsePreferences.class, preferences); 558 childContext.set(IResourcePool.class, resourcePool); 559 final XmiTab ret = ContextInjectionFactory.make(XmiTab.class, childContext); 560 return ret; 561 } 562 createFormTab(Composite composite)563 private Composite createFormTab(Composite composite) { 564 SashForm form = new SashForm(composite, SWT.HORIZONTAL); 565 566 viewer = createTreeViewerArea(form); 567 568 FormToolkit toolkit = new FormToolkit(form.getDisplay()); 569 570 headerContainer = toolkit.createSection(form, Section.TITLE_BAR); 571 headerContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL)); 572 573 // Composite for storing the data 574 Composite contentContainer = toolkit.createComposite(headerContainer, SWT.NONE); 575 headerContainer.setClient(contentContainer); 576 577 StackLayout layout = new StackLayout(); 578 contentContainer.setLayout(layout); 579 580 form.setWeights(new int[] { 2, 5 }); 581 582 viewer.getTree().addKeyListener(new KeyAdapter() { 583 @Override 584 public void keyReleased(final KeyEvent e) { 585 if (e.keyCode == SWT.DEL) { 586 final List<EObject> list = new ArrayList<>(); 587 final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); 588 for (final Object o : ((StructuredSelection) selection).toList()) { 589 if (o instanceof EObject) { 590 list.add((EObject) o); 591 } 592 } 593 if (list.isEmpty() == false) { 594 final Command cmd = DeleteCommand.create(modelProvider.getEditingDomain(), list); 595 if (cmd.canExecute()) { 596 modelProvider.getEditingDomain().getCommandStack().execute(cmd); 597 } 598 } 599 } 600 } 601 }); 602 viewer.addSelectionChangedListener(event -> { 603 if (!event.getSelection().isEmpty()) { 604 final IStructuredSelection s = (IStructuredSelection) event.getSelection(); 605 if (s.getFirstElement() instanceof EObject) { 606 final EObject obj = (EObject) s.getFirstElement(); 607 final AbstractComponentEditor<?> editor1 = getEditor(obj.eClass()); 608 if (editor1 != null) { 609 currentEditor = editor1; 610 headerContainer.setText(editor1.getLabel(obj)); 611 obsManager.runAndCollect(() -> { 612 final Composite comp = editor1.getEditor(contentContainer, s.getFirstElement()); 613 layout.topControl = comp; 614 contentContainer.layout(true); 615 }); 616 } 617 } else { 618 final VirtualEntry<?, ?> entry = (VirtualEntry<?, ?>) s.getFirstElement(); 619 final AbstractComponentEditor<?> editor2 = getEditor(entry.getId()); 620 if (editor2 != null) { 621 currentEditor = editor2; 622 headerContainer.setText(editor2.getLabel(entry)); 623 obsManager.runAndCollect(() -> { 624 final Composite comp = editor2.getEditor(contentContainer, s.getFirstElement()); 625 layout.topControl = comp; 626 contentContainer.layout(true); 627 }); 628 } 629 } 630 631 if (selectionService != null) { 632 selectionService.setSelection(s.getFirstElement()); 633 } 634 } 635 }); 636 637 final MenuManager mgr = new MenuManager(); 638 mgr.setRemoveAllWhenShown(true); 639 mgr.addMenuListener(manager -> { 640 final IStructuredSelection s = (IStructuredSelection) viewer.getSelection(); 641 final List<?> listOfSelections = s.toList(); 642 final int noSelected = listOfSelections.size(); 643 644 boolean addSeparator = false; 645 // single selection 646 if (!s.isEmpty() && noSelected == 1) { 647 List<Action> actions; 648 if (s.getFirstElement() instanceof VirtualEntry) { 649 actions = getEditor(((VirtualEntry<?, ?>) s.getFirstElement()).getId()) 650 .getActions(s.getFirstElement()); 651 if (actions.size() > 0) { 652 final MenuManager addMenu1 = new MenuManager(messages.ModelEditor_AddChild); 653 for (final Action a1 : actions) { 654 addSeparator = true; 655 addMenu1.add(a1); 656 } 657 manager.add(addMenu1); 658 } 659 660 actions = getEditor(((VirtualEntry<?, ?>) s.getFirstElement()).getId()) 661 .getActionsImport(s.getFirstElement()); 662 if (actions.size() > 0) { 663 final MenuManager menu1 = new MenuManager(messages.ModelEditor_Import3x); 664 for (final Action a2 : actions) { 665 addSeparator = true; 666 menu1.add(a2); 667 } 668 manager.add(menu1); 669 } 670 671 if (addSeparator) { 672 manager.add(new Separator()); 673 } 674 675 } else { 676 677 final EObject o = (EObject) s.getFirstElement(); 678 final AbstractComponentEditor<?> editor = getEditor(o.eClass()); 679 680 // Build Add Child menu 681 if (editor != null) { 682 actions = new ArrayList<>(editor.getActions(s.getFirstElement())); 683 } else { 684 actions = new ArrayList<>(); 685 } 686 687 if (actions.size() > 0) { 688 final MenuManager addMenu2 = new MenuManager(messages.ModelEditor_AddChild); 689 for (final Action a3 : actions) { 690 addSeparator = true; 691 addMenu2.add(a3); 692 } 693 manager.add(addMenu2); 694 } 695 696 // Build import menu 697 if (editor != null) { 698 actions = new ArrayList<>(editor.getActionsImport(s.getFirstElement())); 699 } else { 700 actions = new ArrayList<>(); 701 } 702 703 if (actions.size() > 0) { 704 // TODO WIM - extract nls 705 final MenuManager menu2 = new MenuManager(messages.ModelEditor_Import3x); 706 for (final Action a4 : actions) { 707 addSeparator = true; 708 menu2.add(a4); 709 } 710 manager.add(menu2); 711 } 712 713 } 714 } 715 716 // single & multi selection 717 if (noSelected > 0) { 718 719 // add delete entry if there are no virtual entries in selection all selected 720 // elements have a container 721 if (listOfSelections.stream().noneMatch(VirtualEntry.class::isInstance) 722 && listOfSelections.stream().filter(EObject.class::isInstance).map(EObject.class::cast) 723 .map(EObject::eContainer).allMatch(Objects::nonNull)) { 724 addSeparator = true; 725 manager.add(new Action(messages.ModelEditor_Delete, ImageDescriptor 726 .createFromImage(resourcePool.getImageUnchecked(ResourceProvider.IMG_Obj16_cross))) { 727 @Override 728 public void run() { 729 final CompoundCommand cmd = new CompoundCommand(); 730 EditingDomain editingDomain = modelProvider.getEditingDomain(); 731 listOfSelections.forEach(o -> cmd.append(DeleteCommand.create(editingDomain, o))); 732 if (cmd.canExecute() && !cmd.isEmpty()) { 733 editingDomain.getCommandStack().execute(cmd); 734 } 735 } 736 }); 737 } 738 739 if (!isModelFragment() && modelExtractor != null) { 740 manager.add(new Action(messages.ModelEditor_ExtractFragment, ImageDescriptor 741 .createFromImage(resourcePool.getImageUnchecked(ResourceProvider.IMG_ModelFragments))) { 742 @Override 743 public void run() { 744 final ArrayList<MApplicationElement> maes = new ArrayList<>(); 745 for (final Object objSelect : listOfSelections) { 746 EObject container = null; 747 if (objSelect instanceof VirtualEntry) { 748 749 @SuppressWarnings("unchecked") 750 final VirtualEntry<EObject, MApplicationElement> ve = (VirtualEntry<EObject, MApplicationElement>) objSelect; 751 container = ve.getOriginalParent(); 752 final IObservableList<MApplicationElement> list = ve.getList(); 753 final Iterator<MApplicationElement> iterator = list.iterator(); 754 while (iterator.hasNext()) { 755 maes.add(iterator.next()); 756 } 757 758 } else { 759 container = ((EObject) objSelect).eContainer(); 760 final MApplicationElement objSelect2 = (MApplicationElement) objSelect; 761 if (!(objSelect2 instanceof MApplication)) { 762 maes.add(objSelect2); 763 } else { 764 // can't extract application 765 return; 766 } 767 768 } 769 770 final String containerId = ((MApplicationElement) container).getElementId(); 771 if (containerId == null || containerId.length() == 0) { 772 MessageDialog.openError(viewer.getControl().getShell(), null, 773 messages.ModelEditor_ExtractFragment_NoParentId); 774 775 return; 776 } 777 778 } 779 780 if (modelExtractor.extract(viewer.getControl().getShell(), project, maes)) { 781 final Command cmd = DeleteCommand.create(modelProvider.getEditingDomain(), maes); 782 if (cmd.canExecute()) { 783 modelProvider.getEditingDomain().getCommandStack().execute(cmd); 784 } 785 } 786 787 } 788 }); 789 } 790 791 792 } 793 794 final IExtensionRegistry registry = RegistryFactory.getRegistry(); 795 final IExtensionPoint extPoint = registry.getExtensionPoint("org.eclipse.e4.tools.emf.ui.scripting"); //$NON-NLS-1$ 796 final IConfigurationElement[] elements = extPoint.getConfigurationElements(); 797 798 if (elements.length > 0 && !s.isEmpty() && s.getFirstElement() instanceof MApplicationElement 799 && noSelected == 1) { 800 if (addSeparator) { 801 manager.add(new Separator()); 802 } 803 804 addSeparator = false; 805 806 final MenuManager scriptExecute = new MenuManager(messages.ModelEditor_Script); 807 manager.add(scriptExecute); 808 for (final IConfigurationElement e : elements) { 809 final IConfigurationElement le = e; 810 scriptExecute.add(new Action(e.getAttribute("label")) { //$NON-NLS-1$ 811 @Override 812 public void run() { 813 try { 814 final MApplicationElement o = (MApplicationElement) s.getFirstElement(); 815 final IScriptingSupport support = (IScriptingSupport) le 816 .createExecutableExtension("class"); //$NON-NLS-1$ 817 IEclipseContext ctx = null; 818 if (project == null) { 819 if (o instanceof MContext) { 820 ctx = ((MContext) o).getContext(); 821 } else { 822 ctx = ModelUtils.getContainingContext(o); 823 } 824 } 825 826 support.openEditor(viewer.getControl().getShell(), s.getFirstElement(), ctx); 827 } catch (CoreException e) { 828 logger.warn(e); 829 } 830 } 831 }); 832 } 833 } 834 835 if (project != null) { 836 837 if (addSeparator) { 838 manager.add(new Separator()); 839 } 840 841 final Action nlsAction = new Action(messages.ModelEditor_ExternalizeStrings) { 842 @Override 843 public void run() { 844 final ExternalizeStringHandler h = ContextInjectionFactory.make(ExternalizeStringHandler.class, 845 context); 846 ContextInjectionFactory.invoke(h, Execute.class, context); 847 } 848 }; 849 850 final Action extIdAction = new Action(messages.ModelEditor_ExportIds) { 851 @Override 852 public void run() { 853 final ExportIdsHandler h = ContextInjectionFactory.make(ExportIdsHandler.class, context); 854 ContextInjectionFactory.invoke(h, Execute.class, context); 855 } 856 }; 857 858 manager.add(nlsAction); 859 manager.add(extIdAction); 860 } else { 861 if (addSeparator) { 862 manager.add(new Separator()); 863 } 864 865 if (s.getFirstElement() instanceof MUIElement) { 866 final MUIElement el1 = (MUIElement) s.getFirstElement(); 867 if (el1.getWidget() instanceof Control) { 868 manager.add(new Action(messages.ModelEditor_ShowControl) { 869 870 @Override 871 public void run() { 872 ControlHighlighter.show((Control) el1.getWidget()); 873 } 874 }); 875 876 } 877 } 878 879 } 880 881 if (addSeparator) { 882 manager.add(new Separator()); 883 } 884 885 final Action expandAction = new Action(messages.ModelEditor_ExpandSubtree) { 886 @Override 887 public void run() { 888 if (!s.isEmpty()) { 889 if (viewer.getExpandedState(s.getFirstElement())) { 890 viewer.collapseToLevel(s.getFirstElement(), AbstractTreeViewer.ALL_LEVELS); 891 } else { 892 viewer.expandToLevel(s.getFirstElement(), AbstractTreeViewer.ALL_LEVELS); 893 } 894 } 895 } 896 }; 897 898 manager.add(expandAction); 899 900 if (s.getFirstElement() instanceof EObject) { 901 manager.add(new Separator()); 902 final EObject el2 = (EObject) s.getFirstElement(); 903 final Action gotoXmiAction = new Action(messages.ModelEditor_goto_xmi) { 904 @Override 905 public void run() { 906 gotoEObject(TAB_XMI, el2); 907 } 908 }; 909 manager.add(gotoXmiAction); 910 911 if (listTab != null) { 912 if (EmfUtil.getAttribute(el2, "elementId") != null) { //$NON-NLS-1$ 913 final Action gotoListAction = new Action(messages.ModelEditor_goto_list) { 914 @Override 915 public void run() { 916 gotoEObject(TAB_LIST, el2); 917 } 918 }; 919 manager.add(gotoListAction); 920 } 921 } 922 923 } 924 }); 925 926 // Save the stateMask 927 viewer.getTree().addKeyListener(new KeyListener() { 928 @Override 929 public void keyReleased(KeyEvent e) { 930 if (mod1Down && (e.keyCode & SWT.MOD1) == SWT.MOD1) { 931 mod1Down = false; 932 } 933 } 934 935 @Override 936 public void keyPressed(KeyEvent e) { 937 if (!mod1Down && (e.keyCode & SWT.MOD1) == SWT.MOD1) { 938 mod1Down = true; 939 } 940 } 941 }); 942 943 viewer.addTreeListener(new ITreeViewerListener() { 944 @Override 945 public void treeExpanded(final TreeExpansionEvent event) { 946 if (mod1Down) { 947 viewer.getTree().getDisplay() 948 .asyncExec(() -> viewer.expandToLevel(event.getElement(), AbstractTreeViewer.ALL_LEVELS)); 949 } 950 } 951 952 @Override 953 public void treeCollapsed(final TreeExpansionEvent event) { 954 if (mod1Down) { 955 viewer.getTree().getDisplay() 956 .asyncExec(() -> viewer.collapseToLevel(event.getElement(), AbstractTreeViewer.ALL_LEVELS)); 957 } 958 } 959 }); 960 961 viewer.getControl().setMenu(mgr.createContextMenu(viewer.getControl())); 962 viewer.setSelection(new StructuredSelection(modelProvider.getRoot())); 963 964 return form; 965 } 966 getExtensionLookup()967 public IExtensionLookup getExtensionLookup() { 968 return extensionLookup; 969 } 970 isAutoCreateElementId()971 public boolean isAutoCreateElementId() { 972 return autoCreateElementId && project != null; 973 } 974 getProject()975 public IProject getProject() { 976 return project; 977 } 978 getComponentImages()979 public ImageRegistry getComponentImages() { 980 return componentImages; 981 } 982 isShowXMIId()983 public boolean isShowXMIId() { 984 return showXMIId; 985 } 986 loadContributionCreators()987 private void loadContributionCreators() { 988 final IExtensionRegistry registry = RegistryFactory.getRegistry(); 989 final IExtensionPoint extPoint = registry.getExtensionPoint("org.eclipse.e4.tools.emf.ui.editors"); //$NON-NLS-1$ 990 991 for (final IConfigurationElement el : extPoint.getConfigurationElements()) { 992 if (!"contributionClassCreator".equals(el.getName())) { //$NON-NLS-1$ 993 continue; 994 } 995 996 try { 997 contributionCreator.add((IContributionClassCreator) el.createExecutableExtension("class")); //$NON-NLS-1$ 998 } catch (final CoreException e) { 999 logger.warn(e); 1000 } 1001 } 1002 } 1003 getContributionCreator(EClass eClass)1004 public IContributionClassCreator getContributionCreator(EClass eClass) { 1005 for (final IContributionClassCreator c : contributionCreator) { 1006 if (c.isSupported(eClass)) { 1007 return c; 1008 } 1009 } 1010 return null; 1011 } 1012 loadEditorFeatures()1013 private void loadEditorFeatures() { 1014 final IExtensionRegistry registry = RegistryFactory.getRegistry(); 1015 final IExtensionPoint extPoint = registry.getExtensionPoint("org.eclipse.e4.tools.emf.ui.editors"); //$NON-NLS-1$ 1016 1017 for (final IConfigurationElement el : extPoint.getConfigurationElements()) { 1018 if (!"editorfeature".equals(el.getName())) { //$NON-NLS-1$ 1019 continue; 1020 } 1021 1022 try { 1023 editorFeatures.add((IEditorFeature) el.createExecutableExtension("class")); //$NON-NLS-1$ 1024 } catch (final CoreException e) { 1025 logger.warn(e); 1026 } 1027 } 1028 } 1029 isModelFragment()1030 public boolean isModelFragment() { 1031 return fragment; 1032 } 1033 isLiveModel()1034 public boolean isLiveModel() { 1035 return !modelProvider.isSaveable(); 1036 } 1037 getFeatureClasses(EClass eClass, EStructuralFeature feature)1038 public List<FeatureClass> getFeatureClasses(EClass eClass, EStructuralFeature feature) { 1039 final List<FeatureClass> list = new ArrayList<>(); 1040 1041 for (final IEditorFeature f : editorFeatures) { 1042 list.addAll(f.getFeatureClasses(eClass, feature)); 1043 } 1044 1045 return list; 1046 } 1047 createTreeViewerArea(Composite parent)1048 private TreeViewer createTreeViewerArea(Composite parent) { 1049 1050 final Composite treeArea = new Composite(parent, SWT.BORDER); 1051 1052 treeArea.setLayout(new FillLayout()); 1053 treeArea.setData(CSS_CLASS_KEY, "formContainer"); //$NON-NLS-1$ 1054 treeArea.setBackgroundMode(SWT.INHERIT_DEFAULT); 1055 1056 TreeViewer tempViewer = null; 1057 final String property = System 1058 .getProperty(ORG_ECLIPSE_E4_TOOLS_MODELEDITOR_FILTEREDTREE_ENABLED_XMITAB_DISABLED); 1059 if (property != null || preferences.getBoolean(ModelEditorPreferences.TAB_FORM_SEARCH_SHOW, false)) { 1060 final FilteredTree viewParent = new FilteredTree(treeArea, 1061 SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL, new PatternFilter(true)); 1062 tempViewer = viewParent.getViewer(); 1063 } else { 1064 tempViewer = new TreeViewerEx(treeArea, SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL, 1065 emfDocumentProvider, modelProvider); 1066 } 1067 final TreeViewer viewer = tempViewer; 1068 1069 final FontDescriptor italicFontDescriptor = FontDescriptor.createFrom(viewer.getControl().getFont()) 1070 .setStyle(SWT.ITALIC); 1071 viewer.setLabelProvider(new DelegatingStyledCellLabelProvider( 1072 new ComponentLabelProvider(this, messages, italicFontDescriptor))); 1073 final ObservableListTreeContentProvider<Object> contentProvider = new ObservableListTreeContentProvider<>( 1074 new ObservableFactoryImpl(), new TreeStructureAdvisor<Object>() { 1075 }); 1076 viewer.setContentProvider(contentProvider); 1077 1078 final WritableSet<EObject> clearedSet = new WritableSet<>(); 1079 1080 contentProvider.getKnownElements().addSetChangeListener(event -> { 1081 for (final Object o1 : event.diff.getAdditions()) { 1082 if (o1 instanceof EObject) { 1083 clearedSet.add((EObject) o1); 1084 } 1085 } 1086 1087 for (final Object o2 : event.diff.getRemovals()) { 1088 if (o2 instanceof EObject) { 1089 clearedSet.remove(o2); 1090 } 1091 } 1092 }); 1093 1094 for (final FeaturePath p : labelFeaturePaths) { 1095 @SuppressWarnings("unchecked") 1096 final IObservableMap<EObject, Object> map = EMFProperties.value(p).observeDetail(clearedSet); 1097 map.addMapChangeListener(event -> viewer.update(event.diff.getChangedKeys().toArray(), null)); 1098 } 1099 1100 viewer.setInput(modelProvider.getRoot()); 1101 viewer.setAutoExpandLevel(2); 1102 viewer.expandToLevel(viewer.getAutoExpandLevel()); 1103 viewer.addDoubleClickListener(event -> { 1104 final TreeViewer viewer1 = (TreeViewer) event.getViewer(); 1105 final IStructuredSelection thisSelection = (IStructuredSelection) event.getSelection(); 1106 final Object selectedNode = thisSelection.getFirstElement(); 1107 if (mod1Down) { 1108 if (viewer1.getExpandedState(selectedNode)) { 1109 viewer1.setExpandedState(selectedNode, false); 1110 } else { 1111 viewer1.expandToLevel(selectedNode, AbstractTreeViewer.ALL_LEVELS); 1112 } 1113 } else { 1114 viewer1.setExpandedState(selectedNode, !viewer1.getExpandedState(selectedNode)); 1115 } 1116 1117 }); 1118 1119 // Effect of filtered tree implementation (bug 391086) 1120 viewer.getTree().addTreeListener(new TreeAdapter() { 1121 @Override 1122 public void treeCollapsed(TreeEvent e) { 1123 viewer.expandToLevel(viewer.getAutoExpandLevel()); 1124 } 1125 }); 1126 1127 final int ops = DND.DROP_MOVE; 1128 viewer.addDragSupport(ops, new Transfer[] { MemoryTransfer.getInstance() }, new DragListener(viewer)); 1129 viewer.addDropSupport(ops, new Transfer[] { MemoryTransfer.getInstance() }, 1130 new DropListener(viewer, modelProvider.getEditingDomain())); 1131 1132 return viewer; 1133 } 1134 registerContributedVirtualEditors()1135 private void registerContributedVirtualEditors() { 1136 final IExtensionRegistry registry = RegistryFactory.getRegistry(); 1137 final IExtensionPoint extPoint = registry.getExtensionPoint("org.eclipse.e4.tools.emf.ui.editors"); //$NON-NLS-1$ 1138 1139 for (final IConfigurationElement el : extPoint.getConfigurationElements()) { 1140 if (!"virtualeditor".equals(el.getName())) { //$NON-NLS-1$ 1141 continue; 1142 } 1143 1144 final IContributionFactory fact = context.get(IContributionFactory.class); 1145 final AbstractComponentEditor<?> editor = (AbstractComponentEditor<?>) fact 1146 .create("bundleclass://" + el.getContributor().getName() + "/" + el.getAttribute("class"), context); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ 1147 registerEditor(el.getAttribute("id"), editor); //$NON-NLS-1$ 1148 } 1149 } 1150 registerVirtualEditors()1151 private void registerVirtualEditors() { 1152 registerEditor(VIRTUAL_PART_MENU, VPartMenuEditor.class); 1153 registerEditor(VIRTUAL_PART_TRIMS, VPartTrimEditor.class); 1154 registerEditor(VIRTUAL_HANDLER, VHandlerEditor.class); 1155 registerEditor(VIRTUAL_CONTROLS, VControlsEditor.class); 1156 registerEditor(VIRTUAL_BINDING_TABLE, VBindingTableEditor.class); 1157 registerEditor(VIRTUAL_COMMAND, VCommandEditor.class); 1158 registerEditor(VIRTUAL_APPLICATION_WINDOWS, VApplicationWindowEditor.class); 1159 registerEditor(VIRTUAL_WINDOW_WINDOWS, VWindowWindowsEditor.class); 1160 registerEditor(VIRTUAL_PERSPECTIVE_WINDOWS, VPerspectiveWindowsEditor.class); 1161 registerEditor(VIRTUAL_WINDOW_CONTROLS, VWindowControlEditor.class); 1162 registerEditor(VIRTUAL_WINDOW_SNIPPETS, VSnippetsEditor.class); 1163 registerEditor(VIRTUAL_PART_DESCRIPTORS, VPartDescriptor.class); 1164 registerEditor(VIRTUAL_PARTDESCRIPTOR_MENU, VPartDescriptorMenuEditor.class); 1165 registerEditor(VIRTUAL_PARTDESCRIPTOR_TRIMS, VPartDescriptorTrimEditor.class); 1166 registerEditor(VIRTUAL_TRIMMED_WINDOW_TRIMS, VWindowTrimEditor.class); 1167 registerEditor(VIRTUAL_ADDONS, VApplicationAddons.class); 1168 registerEditor(VIRTUAL_MENU_CONTRIBUTIONS, VMenuContributionsEditor.class); 1169 registerEditor(VIRTUAL_TOOLBAR_CONTRIBUTIONS, VToolBarContributionsEditor.class); 1170 registerEditor(VIRTUAL_TRIM_CONTRIBUTIONS, VTrimContributionsEditor.class); 1171 registerEditor(VIRTUAL_WINDOW_SHARED_ELEMENTS, VWindowSharedElementsEditor.class); 1172 registerEditor(VIRTUAL_MODEL_FRAGEMENTS, VModelFragmentsEditor.class); 1173 registerEditor(VIRTUAL_MODEL_IMPORTS, VModelImportsEditor.class); 1174 registerEditor(VIRTUAL_CATEGORIES, VApplicationCategoriesEditor.class); 1175 registerEditor(VIRTUAL_PARAMETERS, VItemParametersEditor.class); 1176 registerEditor(VIRTUAL_ROOT_CONTEXTS, VRootBindingContexts.class); 1177 registerEditor(VIRTUAL_PERSPECTIVE_CONTROLS, VPerspectiveControlEditor.class); 1178 registerEditor(VIRTUAL_PERSPECTIVE_TRIMS, VPerspectiveTrimEditor.class); 1179 registerEditor(VIRTUAL_SNIPPETS, VSnippetsEditor.class); 1180 } 1181 setSelection(Object element)1182 public void setSelection(Object element) { 1183 viewer.setSelection(new StructuredSelection(element)); 1184 } 1185 registerContributedEditors()1186 private void registerContributedEditors() { 1187 final IExtensionRegistry registry = RegistryFactory.getRegistry(); 1188 final IExtensionPoint extPoint = registry.getExtensionPoint("org.eclipse.e4.tools.emf.ui.editors"); //$NON-NLS-1$ 1189 1190 for (final IConfigurationElement el : extPoint.getConfigurationElements()) { 1191 if (!"editor".equals(el.getName())) { //$NON-NLS-1$ 1192 continue; 1193 } 1194 1195 try { 1196 final IEditorDescriptor desc = (IEditorDescriptor) el.createExecutableExtension("descriptorClass"); //$NON-NLS-1$ 1197 final EClass eClass = desc.getEClass(); 1198 final IContributionFactory fact = context.get(IContributionFactory.class); 1199 final AbstractComponentEditor<?> editor = (AbstractComponentEditor<?>) fact.create( 1200 "bundleclass://" + el.getContributor().getName() + "/" + desc.getEditorClass().getName(), //$NON-NLS-1$ //$NON-NLS-2$ 1201 context); 1202 registerEditor(eClass, editor); 1203 } catch (final CoreException e) { 1204 e.printStackTrace(); 1205 } 1206 } 1207 } 1208 registerContributedEditorTabs()1209 private void registerContributedEditorTabs() { 1210 final IExtensionRegistry registry = RegistryFactory.getRegistry(); 1211 final IExtensionPoint extPoint = registry.getExtensionPoint("org.eclipse.e4.tools.emf.ui.editors"); //$NON-NLS-1$ 1212 for (final IConfigurationElement el : extPoint.getConfigurationElements()) { 1213 if (!"editorTab".equals(el.getName())) { //$NON-NLS-1$ 1214 continue; 1215 } 1216 1217 try { 1218 final Object o = el.createExecutableExtension("contribution"); //$NON-NLS-1$ 1219 if (o instanceof AbstractElementEditorContribution) { 1220 final AbstractElementEditorContribution contribution = (AbstractElementEditorContribution) o; 1221 ContextInjectionFactory.inject(contribution, context); 1222 final Class<?> contribElem = contribution.getContributableTo(); 1223 if (contribElem == null) { 1224 continue; 1225 } 1226 if (!tabContributions.containsKey(contribElem)) { 1227 tabContributions.put(contribElem, new ArrayList<AbstractElementEditorContribution>()); 1228 } 1229 final List<AbstractElementEditorContribution> res = tabContributions.get(contribElem); 1230 res.add(contribution); 1231 } 1232 } catch (final CoreException e) { 1233 e.printStackTrace(); 1234 } 1235 } 1236 } 1237 getTabContributionsForClass(Class<?> clazz)1238 public List<AbstractElementEditorContribution> getTabContributionsForClass(Class<?> clazz) { 1239 final List<AbstractElementEditorContribution> ret = new ArrayList<>(); 1240 for (Map.Entry<Class<?>, List<AbstractElementEditorContribution>> entry : tabContributions.entrySet()) { 1241 Class<?> clasz = entry.getKey(); 1242 if (clasz.isAssignableFrom(clazz)) { 1243 ret.addAll(entry.getValue()); 1244 } 1245 } 1246 return ret; 1247 } 1248 registerDefaultEditors()1249 private void registerDefaultEditors() { 1250 1251 registerEditor(ApplicationPackageImpl.Literals.APPLICATION, ApplicationEditor.class); 1252 registerEditor(ApplicationPackageImpl.Literals.ADDON, AddonsEditor.class); 1253 1254 registerEditor(CommandsPackageImpl.Literals.KEY_BINDING, KeyBindingEditor.class); 1255 registerEditor(CommandsPackageImpl.Literals.HANDLER, HandlerEditor.class); 1256 registerEditor(CommandsPackageImpl.Literals.COMMAND, CommandEditor.class); 1257 registerEditor(CommandsPackageImpl.Literals.COMMAND_PARAMETER, CommandParameterEditor.class); 1258 registerEditor(CommandsPackageImpl.Literals.PARAMETER, ParameterEditor.class); 1259 registerEditor(CommandsPackageImpl.Literals.BINDING_TABLE, BindingTableEditor.class); 1260 registerEditor(CommandsPackageImpl.Literals.BINDING_CONTEXT, BindingContextEditor.class); 1261 registerEditor(CommandsPackageImpl.Literals.CATEGORY, CategoryEditor.class); 1262 1263 registerEditor(MenuPackageImpl.Literals.TOOL_BAR, ToolBarEditor.class); 1264 registerEditor(MenuPackageImpl.Literals.DIRECT_TOOL_ITEM, DirectToolItemEditor.class); 1265 registerEditor(MenuPackageImpl.Literals.HANDLED_TOOL_ITEM, HandledToolItemEditor.class); 1266 registerEditor(MenuPackageImpl.Literals.TOOL_BAR_SEPARATOR, ToolBarSeparatorEditor.class); 1267 registerEditor(MenuPackageImpl.Literals.TOOL_CONTROL, ToolControlEditor.class); 1268 registerEditor(MenuPackageImpl.Literals.MENU, MenuEditor.class); 1269 registerEditor(MenuPackageImpl.Literals.POPUP_MENU, PopupMenuEditor.class); 1270 registerEditor(MenuPackageImpl.Literals.MENU_SEPARATOR, MenuSeparatorEditor.class); 1271 registerEditor(MenuPackageImpl.Literals.HANDLED_MENU_ITEM, HandledMenuItemEditor.class); 1272 registerEditor(MenuPackageImpl.Literals.DIRECT_MENU_ITEM, DirectMenuItemEditor.class); 1273 registerEditor(MenuPackageImpl.Literals.MENU_CONTRIBUTION, MenuContributionEditor.class); 1274 registerEditor(MenuPackageImpl.Literals.TOOL_BAR_CONTRIBUTION, ToolBarContributionEditor.class); 1275 registerEditor(MenuPackageImpl.Literals.TRIM_CONTRIBUTION, TrimContributionEditor.class); 1276 registerEditor(MenuPackageImpl.Literals.DYNAMIC_MENU_CONTRIBUTION, DynamicMenuContributionEditor.class); 1277 1278 registerEditor(UiPackageImpl.Literals.CORE_EXPRESSION, CoreExpressionEditor.class); 1279 registerEditor(UiPackageImpl.Literals.IMPERATIVE_EXPRESSION, ImperativeExpressionEditor.class); 1280 1281 registerEditor(BasicPackageImpl.Literals.COMPOSITE_PART, CompositePartEditor.class); 1282 registerEditor(BasicPackageImpl.Literals.PART, PartEditor.class); 1283 registerEditor(BasicPackageImpl.Literals.WINDOW, WindowEditor.class); 1284 registerEditor(BasicPackageImpl.Literals.TRIMMED_WINDOW, TrimmedWindowEditor.class); 1285 registerEditor(BasicPackageImpl.Literals.PART_SASH_CONTAINER, PartSashContainerEditor.class); 1286 registerEditor(AdvancedPackageImpl.Literals.AREA, AreaEditor.class); 1287 registerEditor(BasicPackageImpl.Literals.PART_STACK, PartStackEditor.class); 1288 registerEditor(BasicPackageImpl.Literals.TRIM_BAR, TrimBarEditor.class); 1289 1290 registerEditor( 1291 org.eclipse.e4.ui.model.application.descriptor.basic.impl.BasicPackageImpl.Literals.PART_DESCRIPTOR, 1292 PartDescriptorEditor.class); 1293 1294 registerEditor(AdvancedPackageImpl.Literals.PERSPECTIVE_STACK, PerspectiveStackEditor.class); 1295 registerEditor(AdvancedPackageImpl.Literals.PERSPECTIVE, PerspectiveEditor.class); 1296 registerEditor(AdvancedPackageImpl.Literals.PLACEHOLDER, PlaceholderEditor.class); 1297 1298 registerEditor(FragmentPackageImpl.Literals.MODEL_FRAGMENTS, ModelFragmentsEditor.class); 1299 registerEditor(FragmentPackageImpl.Literals.STRING_MODEL_FRAGMENT, StringModelFragment.class); 1300 } 1301 tabListShow(Boolean show)1302 public void tabListShow(Boolean show) { 1303 if (editorTabFolder == null) { 1304 return; 1305 } 1306 if (show == false) { 1307 if (listTab != null) { 1308 // remove the tab from the folder 1309 listTab.getTabItem().dispose(); 1310 ContextInjectionFactory.uninject(listTab, listTab.getContext()); 1311 listTab = null; 1312 } 1313 } else { 1314 if (listTab == null) { 1315 final IEclipseContext child = context.createChild(); 1316 child.set(CTabFolder.class, editorTabFolder); 1317 child.set(EMFDocumentResourceMediator.class, emfDocumentProvider); 1318 child.set(IGotoObject.class, this); 1319 child.set(Messages.class, messages); 1320 listTab = ContextInjectionFactory.make(ListTab.class, child); 1321 tabItemList = listTab.getTabItem(); 1322 } 1323 } 1324 } 1325 1326 @Inject setNotVisibleColor(@referenceModelEditorPreferences.NOT_VISIBLE_COLOR) String prefColorText)1327 public void setNotVisibleColor(@Preference(ModelEditorPreferences.NOT_VISIBLE_COLOR) String prefColorText) { 1328 final RGB current = JFaceResources.getColorRegistry().getRGB(ComponentLabelProvider.NOT_VISIBLE_KEY); 1329 RGB prefColor = StringConverter.asRGB(prefColorText, new RGB(200, 200, 200)); 1330 1331 if (current == null || !current.equals(prefColor)) { 1332 JFaceResources.getColorRegistry().put(ComponentLabelProvider.NOT_VISIBLE_KEY, prefColor); 1333 } 1334 1335 if (viewer != null) { 1336 viewer.refresh(); 1337 viewer.getControl().redraw(); 1338 } 1339 } 1340 1341 @Inject setNotRenderedColor(@referenceModelEditorPreferences.NOT_RENDERED_COLOR) String prefColorText)1342 public void setNotRenderedColor(@Preference(ModelEditorPreferences.NOT_RENDERED_COLOR) String prefColorText) { 1343 RGB prefColor = StringConverter.asRGB(prefColorText, new RGB(200, 200, 200)); 1344 final RGB current = JFaceResources.getColorRegistry().getRGB(ComponentLabelProvider.NOT_RENDERED_KEY); 1345 1346 if (current == null || !current.equals(prefColor)) { 1347 JFaceResources.getColorRegistry().put(ComponentLabelProvider.NOT_RENDERED_KEY, prefColor); 1348 } 1349 1350 if (viewer != null) { 1351 viewer.refresh(); 1352 viewer.getControl().redraw(); 1353 } 1354 } 1355 1356 @Inject setNotVisibleRenderedColor( @referenceModelEditorPreferences.NOT_VISIBLE_AND_RENDERED_COLOR) String prefColorText)1357 public void setNotVisibleRenderedColor( 1358 @Preference(ModelEditorPreferences.NOT_VISIBLE_AND_RENDERED_COLOR) String prefColorText) { 1359 RGB prefColor = StringConverter.asRGB(prefColorText, new RGB(200, 200, 200)); 1360 final RGB current = JFaceResources.getColorRegistry() 1361 .getRGB(ComponentLabelProvider.NOT_VISIBLE_AND_RENDERED_KEY); 1362 1363 if (current == null || !current.equals(prefColor)) { 1364 JFaceResources.getColorRegistry().put(ComponentLabelProvider.NOT_VISIBLE_AND_RENDERED_KEY, prefColor); 1365 } 1366 1367 if (viewer != null) { 1368 viewer.refresh(); 1369 viewer.getControl().redraw(); 1370 } 1371 } 1372 registerEditor(EClass eClass, Class<? extends AbstractComponentEditor<?>> clazz)1373 private void registerEditor(EClass eClass, Class<? extends AbstractComponentEditor<?>> clazz) { 1374 registerEditor(eClass.getInstanceClassName(), clazz); 1375 } 1376 1377 /** 1378 * Register a class to use to create an editor for a given key 1379 * 1380 * @param ley 1381 * @param clazz 1382 */ registerEditor(String key, Class<? extends AbstractComponentEditor<?>> clazz)1383 private void registerEditor(String key, Class<? extends AbstractComponentEditor<?>> clazz) { 1384 editorsClasses.put(key, clazz); 1385 } 1386 1387 /** 1388 * Register directly a created editor for a given key 1389 * 1390 * @param instanceClassName 1391 * @param clazz 1392 */ registerEditor(String key, AbstractComponentEditor<?> editor)1393 private void registerEditor(String key, AbstractComponentEditor<?> editor) { 1394 editors.put(key, editor); 1395 } 1396 1397 /** 1398 * Get editor from an eClass. May return the registered editor for this eclass, 1399 * or the editor for a parent EClass or the default editor 1400 * 1401 * @param eClass the eClass to get editor for 1402 * @return the {@link AbstractComponentEditor} found (never null). 1403 */ getEditor(EClass eClass)1404 public AbstractComponentEditor<?> getEditor(EClass eClass) { 1405 AbstractComponentEditor<?> editor = getEditor(eClass.getInstanceClassName(), false); 1406 1407 if (editor == null) { 1408 // May be can try to use the ancestor editor if not found or the default editor 1409 for (final EClass cl : eClass.getESuperTypes()) { 1410 editor = getEditor(cl); 1411 if (editor != null) { 1412 break; 1413 } 1414 } 1415 1416 // Editor is still null ? , will use the default editor 1417 if (editor == null) { 1418 editor = ContextInjectionFactory.make(DefaultEditor.class, context); 1419 } 1420 1421 // register the parent or default editor 1422 editors.put(eClass.getInstanceClassName(), editor); 1423 } 1424 1425 return editor; 1426 1427 } 1428 getEditor(String key)1429 public AbstractComponentEditor<?> getEditor(String key) { 1430 return getEditor(key, true); 1431 } 1432 1433 /** 1434 * get editor from a string key. 1435 * 1436 * @param key : the editor string key 1437 * @param createDefaultIfNull if true, returns the default editor if no editor 1438 * found 1439 * @return the {@link AbstractComponentEditor} if exists. Never null if 1440 * createDefaultIfNull is true 1441 */ getEditor(String key, boolean createDefaultIfNull)1442 private AbstractComponentEditor<?> getEditor(String key, boolean createDefaultIfNull) { 1443 AbstractComponentEditor<?> editor = editors.get(key); 1444 1445 if (editor == null) { 1446 1447 // Editor not yet created in the map... must create instance using registered 1448 // class 1449 Class<? extends AbstractComponentEditor<?>> cz = editorsClasses.get(key); 1450 if (cz != null) { 1451 editor = ContextInjectionFactory.make(cz, context); 1452 editors.put(key, editor); 1453 1454 // Then manage the feature maps... 1455 manageFeatureMap(editor); 1456 } 1457 1458 } 1459 1460 return editor; 1461 } 1462 manageFeatureMap(AbstractComponentEditor<?> editor)1463 private void manageFeatureMap(AbstractComponentEditor<?> editor) { 1464 for (final FeaturePath p : editor.getLabelProperties()) { 1465 boolean found = false; 1466 for (final FeaturePath tmp : labelFeaturePaths) { 1467 if (equalsPaths(p, tmp)) { 1468 found = true; 1469 break; 1470 } 1471 } 1472 1473 if (!found) { 1474 labelFeaturePaths.add(p); 1475 } 1476 } 1477 1478 } 1479 registerEditor(EClass eClass, AbstractComponentEditor<?> editor)1480 public void registerEditor(EClass eClass, AbstractComponentEditor<?> editor) { 1481 editors.put(eClass.getInstanceClassName(), editor); 1482 manageFeatureMap(editor); 1483 } 1484 equalsPaths(FeaturePath p1, FeaturePath p2)1485 private boolean equalsPaths(FeaturePath p1, FeaturePath p2) { 1486 if (p1.getFeaturePath().length == p2.getFeaturePath().length) { 1487 for (int i = 0; i < p1.getFeaturePath().length; i++) { 1488 if (!p1.getFeaturePath()[i].equals(p2.getFeaturePath()[i])) { 1489 return false; 1490 } 1491 } 1492 1493 return true; 1494 } 1495 1496 return false; 1497 } 1498 1499 @Persist doSave(@ptional IProgressMonitor monitor)1500 public void doSave(@Optional IProgressMonitor monitor) { 1501 1502 try { 1503 setSaving(true); 1504 if (modelProvider.isSaveable()) { 1505 modelProvider.save(); 1506 } 1507 } finally { 1508 setSaving(false); 1509 } 1510 } 1511 setSaving(boolean saving)1512 private void setSaving(boolean saving) { 1513 this.saving = saving; 1514 } 1515 1516 /** 1517 * @return true if the editor is currently in the progress of saving. 1518 */ isSaving()1519 protected boolean isSaving() { 1520 return saving; 1521 } 1522 1523 @Focus setFocus()1524 public void setFocus() { 1525 if (clipboardHandler == null) { 1526 clipboardHandler = new ClipboardHandler(); 1527 } 1528 if (clipboardService != null) { 1529 clipboardService.setHandler(clipboardHandler); 1530 } 1531 } 1532 setHeaderTitle(String title)1533 public void setHeaderTitle(String title) { 1534 headerContainer.setText(title); 1535 } 1536 1537 @PreDestroy dispose()1538 void dispose() { 1539 try { 1540 obsManager.dispose(); 1541 } catch (final Exception e) { 1542 e.printStackTrace(); 1543 } 1544 1545 if (project == null) { 1546 context.get(Display.class).removeFilter(SWT.MouseUp, keyListener); 1547 } 1548 if (xmiTab != null) { 1549 ContextInjectionFactory.uninject(xmiTab, xmiTab.getContext()); 1550 } 1551 } 1552 getModelProvider()1553 public IModelResource getModelProvider() { 1554 return modelProvider; 1555 } 1556 1557 class ClipboardHandler implements Handler { 1558 1559 @Override paste()1560 public void paste() { 1561 if (editorTabFolder.getSelectionIndex() == 0) { 1562 if (viewer.getControl().getDisplay().getFocusControl() == viewer.getControl()) { 1563 handleStructurePaste(); 1564 } else if (currentEditor != null) { 1565 currentEditor.handlePaste(); 1566 } 1567 } else { 1568 xmiTab.paste(); 1569 } 1570 } 1571 1572 @SuppressWarnings("unchecked") handleStructurePaste()1573 private void handleStructurePaste() { 1574 final Clipboard clip = new Clipboard(viewer.getControl().getDisplay()); 1575 Object contents = clip.getContents(MemoryTransfer.getInstance()); 1576 clip.dispose(); 1577 if (contents == null) { 1578 return; 1579 } 1580 List<EObject> toCopy = new ArrayList<>(); 1581 if (contents instanceof EObject) { 1582 toCopy.add(EcoreUtil.copy((EObject) contents)); 1583 } else if (contents instanceof List<?>) { 1584 List<Object> list = (List<Object>) contents; 1585 for (Object object : list) { 1586 if (object instanceof EObject) { 1587 toCopy.add(EcoreUtil.copy((EObject) object)); 1588 } 1589 } 1590 } 1591 1592 if (toCopy.isEmpty()) { 1593 return; 1594 } 1595 1596 final Object parent = ((IStructuredSelection) viewer.getSelection()).getFirstElement(); 1597 EObject probe = toCopy.get(0); 1598 1599 EStructuralFeature feature = null; 1600 EObject container = null; 1601 if (parent instanceof VirtualEntry) { 1602 final VirtualEntry<EObject, ?> v = (VirtualEntry<EObject, ?>) parent; 1603 feature = ((IEMFProperty) v.getProperty()).getStructuralFeature(); 1604 container = v.getOriginalParent(); 1605 } else if (parent instanceof EObject) { 1606 container = (EObject) parent; 1607 if (container instanceof MElementContainer<?>) { 1608 feature = UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN; 1609 } else { 1610 feature = determineTargetFeature(probe, container); 1611 if (feature == null && container.eClass().equals(probe.eClass()) 1612 && container.eContainer() != null) { 1613 // it seems the user has still the original selection active, 1614 // try to find the target feature using the container's container 1615 container = container.eContainer(); 1616 feature = determineTargetFeature(probe, container); 1617 } 1618 } 1619 } 1620 1621 if (container == null) { 1622 // no container selected that we can paste into 1623 return; 1624 } 1625 1626 if (feature == null) { 1627 // no target feature derivable from current state of the editor 1628 return; 1629 } 1630 1631 List<EClass> targetChildrenClasses = new ArrayList<>(); 1632 1633 if (container instanceof MStringModelFragment) { 1634 MStringModelFragment stringModelFragment = (MStringModelFragment) container; 1635 EClass targetType = StringModelFragment.findContainerType(stringModelFragment); 1636 if (targetType != null) { 1637 EStructuralFeature targetFeature = targetType 1638 .getEStructuralFeature(stringModelFragment.getFeaturename()); 1639 if (targetFeature != null) { 1640 List<FeatureClass> classes = StringModelFragment.getTargetChildrenClasses(targetType, 1641 targetFeature.getName()); 1642 for (FeatureClass fclass : classes) { 1643 targetChildrenClasses.add(fclass.eClass); 1644 } 1645 } 1646 } 1647 } 1648 1649 CompoundCommand cc = new CompoundCommand(); 1650 Object pastedObject = null; // The single pasted object if single paste (for undo/redo message) 1651 for (EObject eObject : toCopy) { 1652 if (!isValidTarget(parent, eObject, false)) { 1653 // the object to paste does not fit into the target feature 1654 continue; 1655 } 1656 if (!targetChildrenClasses.isEmpty() && !targetChildrenClasses.contains(eObject.eClass())) { 1657 // there is a limited list of allowed target types 1658 // and a fragment that is pointing to a different feature 1659 continue; 1660 } 1661 1662 if (feature == FragmentPackageImpl.Literals.MODEL_FRAGMENTS__IMPORTS) { 1663 final MApplicationElement el = (MApplicationElement) EcoreUtil.create(eObject.eClass()); 1664 el.setElementId(((MApplicationElement) eObject).getElementId()); 1665 final Command cmd = AddCommand.create(getModelProvider().getEditingDomain(), container, feature, 1666 el); 1667 if (cmd.canExecute()) { 1668 pastedObject = el; 1669 cc.append(cmd); 1670 } 1671 return; 1672 } 1673 1674 final Command cmd = AddCommand.create(getModelProvider().getEditingDomain(), container, feature, 1675 eObject); 1676 pastedObject = eObject; 1677 if (cmd.canExecute()) { 1678 cc.append(cmd); 1679 if (isLiveModel()) { 1680 if (container instanceof MElementContainer<?> && probe instanceof MUIElement) { 1681 // the last selection wins 1682 ((MElementContainer<MUIElement>) container).setSelectedElement((MUIElement) eObject); 1683 } 1684 } 1685 } 1686 } 1687 if (!cc.isEmpty()) { 1688 if (cc.getCommandList().size() == 1) { 1689 cc.setLabel(messages.ModelEditor_Paste + " " + getObjectNameForCommand(pastedObject)); //$NON-NLS-1$ 1690 } else { 1691 cc.setLabel(messages.ModelEditor_PasteObjects); 1692 } 1693 1694 getModelProvider().getEditingDomain().getCommandStack().execute(cc); 1695 } 1696 } 1697 determineTargetFeature(EObject probe, EObject container)1698 private EStructuralFeature determineTargetFeature(EObject probe, EObject container) { 1699 final EClass eClass = container.eClass(); 1700 for (final EStructuralFeature f : eClass.getEAllReferences()) { 1701 if (ModelUtils.getTypeArgument(eClass, f.getEGenericType()).isInstance(probe)) { 1702 return f; 1703 } 1704 } 1705 return null; 1706 } 1707 1708 @Override copy()1709 public void copy() { 1710 if (editorTabFolder.getSelectionIndex() == 0) { 1711 if (viewer.getControl().getDisplay().getFocusControl() == viewer.getControl()) { 1712 handleStructureCopy(); 1713 } else if (currentEditor != null) { 1714 currentEditor.handleCopy(); 1715 } 1716 } else { 1717 xmiTab.copy(); 1718 } 1719 } 1720 handleStructureCopy()1721 private void handleStructureCopy() { 1722 IStructuredSelection structuredSelection = (IStructuredSelection) viewer.getSelection(); 1723 List<EObject> toCopy = new ArrayList<>(); 1724 for (Object obj : structuredSelection.toList()) { 1725 if (obj != null && obj instanceof EObject) { 1726 EObject copy = EcoreUtil.copy((EObject) obj); 1727 toCopy.add(copy); 1728 } 1729 } 1730 if (toCopy.isEmpty()) { 1731 return; 1732 } 1733 final Clipboard clip = new Clipboard(viewer.getControl().getDisplay()); 1734 clip.setContents(new Object[] { toCopy }, new Transfer[] { MemoryTransfer.getInstance() }); 1735 clip.dispose(); 1736 } 1737 1738 @Override cut()1739 public void cut() { 1740 if (editorTabFolder.getSelectionIndex() == 0) { 1741 if (viewer.getControl().getDisplay().getFocusControl() == viewer.getControl()) { 1742 handleStructureCut(); 1743 } else if (currentEditor != null) { 1744 currentEditor.handleCut(); 1745 } 1746 } else { 1747 xmiTab.cut(); 1748 } 1749 } 1750 handleStructureCut()1751 private void handleStructureCut() { 1752 1753 // Manage multiple cut objects (bug #532070) 1754 Collection<EObject> objectsToCut = new ArrayList<>(); 1755 final Clipboard clip = new Clipboard(viewer.getControl().getDisplay()); 1756 for (Object o : ((IStructuredSelection) viewer.getSelection()).toList()) { 1757 if (o != null && o instanceof EObject) { 1758 objectsToCut.add((EObject) o); 1759 } 1760 } 1761 1762 Command cmd = null; 1763 if (objectsToCut.isEmpty()) { 1764 return; 1765 } else if (objectsToCut.size() == 1) { 1766 // Only 1 object to cut... create a removeCommand 1767 EObject o = objectsToCut.iterator().next(); 1768 cmd = RemoveCommand.create(getModelProvider().getEditingDomain(), o.eContainer(), 1769 o.eContainingFeature(), o); 1770 ((AbstractCommand) cmd).setLabel(messages.ModelEditor_Cut + " " + getObjectNameForCommand(o)); //$NON-NLS-1$ 1771 } else { 1772 // There are more than one object to remove -> Compound command. 1773 CompoundCommand cc = new CompoundCommand(); 1774 cc.setLabel(messages.ModelEditor_CutObjects); 1775 for (EObject o : objectsToCut) { 1776 cc.append(RemoveCommand.create(getModelProvider().getEditingDomain(), o.eContainer(), 1777 o.eContainingFeature(), o)); 1778 } 1779 cmd = cc; 1780 } 1781 1782 if (cmd.canExecute()) { 1783 // Now can set the clipboard... 1784 clip.setContents(new Object[] { objectsToCut }, new Transfer[] { MemoryTransfer.getInstance() }); 1785 getModelProvider().getEditingDomain().getCommandStack().execute(cmd); 1786 } 1787 1788 clip.dispose(); 1789 } 1790 } 1791 1792 public class ObservableFactoryImpl implements IObservableFactory<Object, IObservableList<Object>> { 1793 1794 @SuppressWarnings("unchecked") 1795 @Override createObservable(Object target)1796 public IObservableList<Object> createObservable(Object target) { 1797 if (target instanceof IObservableList) { 1798 return new WritableList<>((List<Object>) target, Object.class); 1799 } else if (target instanceof VirtualEntry) { 1800 return ((VirtualEntry<?, Object>) target).getList(); 1801 } else { 1802 final AbstractComponentEditor<EObject> editor = (AbstractComponentEditor<EObject>) getEditor( 1803 ((EObject) target).eClass()); 1804 if (editor != null) { 1805 return (IObservableList<Object>) editor.getChildList(target); 1806 } 1807 } 1808 1809 return null; 1810 } 1811 } 1812 1813 static class DragListener extends DragSourceAdapter { 1814 private final TreeViewer viewer; 1815 DragListener(TreeViewer viewer)1816 public DragListener(TreeViewer viewer) { 1817 this.viewer = viewer; 1818 } 1819 1820 @Override dragStart(DragSourceEvent event)1821 public void dragStart(DragSourceEvent event) { 1822 final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); 1823 event.doit = !selection.isEmpty() && (selection.getFirstElement() instanceof MApplicationElement 1824 || selection.getFirstElement() instanceof MModelFragment); 1825 } 1826 1827 @Override dragSetData(DragSourceEvent event)1828 public void dragSetData(DragSourceEvent event) { 1829 final IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); 1830 event.data = selection.toArray(); 1831 } 1832 } 1833 1834 class DropListener extends ViewerDropAdapter { 1835 private final EditingDomain domain; 1836 DropListener(Viewer viewer, EditingDomain domain)1837 protected DropListener(Viewer viewer, EditingDomain domain) { 1838 super(viewer); 1839 this.domain = domain; 1840 } 1841 1842 @Override performDrop(Object data)1843 public boolean performDrop(Object data) { 1844 if (!(data instanceof Object[])) { 1845 return false; 1846 } 1847 final Object[] dropDataArray = (Object[]) data; 1848 for (final Object object : dropDataArray) { 1849 final boolean result = performSingleDrop(object); 1850 if (!result) { 1851 return false; 1852 } 1853 } 1854 return true; 1855 } 1856 1857 @SuppressWarnings("unchecked") performSingleDrop(Object data)1858 public boolean performSingleDrop(Object data) { 1859 if (getCurrentLocation() == LOCATION_ON) { 1860 EStructuralFeature feature = null; 1861 EObject parent = null; 1862 if (getCurrentTarget() instanceof MElementContainer<?>) { 1863 feature = UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN; 1864 parent = (EObject) getCurrentTarget(); 1865 } else if (getCurrentTarget() instanceof VirtualEntry) { 1866 1867 final VirtualEntry<EObject, ?> entry = (VirtualEntry<EObject, ?>) getCurrentTarget(); 1868 final IListProperty<?, ?> prop = entry.getProperty(); 1869 if (prop instanceof IEMFProperty) { 1870 feature = ((IEMFProperty) prop).getStructuralFeature(); 1871 parent = entry.getOriginalParent(); 1872 1873 } 1874 } else if (getCurrentTarget() instanceof EObject) { 1875 parent = (EObject) getCurrentTarget(); 1876 for (final EStructuralFeature f : parent.eClass().getEAllStructuralFeatures()) { 1877 final EClassifier cl = ModelUtils.getTypeArgument(parent.eClass(), f.getEGenericType()); 1878 if (cl.isInstance(data)) { 1879 feature = f; 1880 break; 1881 } 1882 } 1883 } 1884 1885 if (feature != null && parent != null) { 1886 final Command cmd = createRemoveAddCommand(data, feature, parent, CommandParameter.NO_INDEX); 1887 if (cmd.canExecute()) { 1888 domain.getCommandStack().execute(cmd); 1889 if (isLiveModel()) { 1890 if (parent instanceof MElementContainer<?> && data instanceof MUIElement) { 1891 ((MElementContainer<MUIElement>) parent).setSelectedElement((MUIElement) data); 1892 } 1893 } 1894 return true; 1895 } 1896 } 1897 } else if (getCurrentLocation() == LOCATION_AFTER || getCurrentLocation() == LOCATION_BEFORE) { 1898 EStructuralFeature feature = null; 1899 EObject parent = null; 1900 1901 final TreeItem item = (TreeItem) getCurrentEvent().item; 1902 if (item != null) { 1903 final TreeItem parentItem = item.getParentItem(); 1904 if (parentItem != null) { 1905 if (parentItem.getData() instanceof VirtualEntry) { 1906 final VirtualEntry<EObject, ?> vE = (VirtualEntry<EObject, ?>) parentItem.getData(); 1907 parent = vE.getOriginalParent(); 1908 feature = ((IEMFProperty) vE.getProperty()).getStructuralFeature(); 1909 } else if (parentItem.getData() instanceof MElementContainer<?>) { 1910 parent = (EObject) parentItem.getData(); 1911 feature = UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN; 1912 } else if (parentItem.getData() instanceof EObject) { 1913 parent = (EObject) parentItem.getData(); 1914 for (final EStructuralFeature f : parent.eClass().getEAllStructuralFeatures()) { 1915 final EClassifier cl = ModelUtils.getTypeArgument(parent.eClass(), f.getEGenericType()); 1916 if (cl.isInstance(data)) { 1917 feature = f; 1918 break; 1919 } 1920 } 1921 } 1922 } 1923 } 1924 1925 if (feature == FragmentPackageImpl.Literals.MODEL_FRAGMENTS__IMPORTS && parent != null) { 1926 final MApplicationElement el = (MApplicationElement) EcoreUtil.create(((EObject) data).eClass()); 1927 el.setElementId(((MApplicationElement) data).getElementId()); 1928 final Command cmd = createRemoveAddCommand(data, feature, parent, CommandParameter.NO_INDEX); 1929 if (cmd.canExecute()) { 1930 domain.getCommandStack().execute(cmd); 1931 } 1932 return true; 1933 } 1934 1935 if (feature != null && parent != null && parent.eGet(feature) instanceof List<?>) { 1936 final List<Object> list = (List<Object>) parent.eGet(feature); 1937 int index = list.indexOf(getCurrentTarget()); 1938 1939 if (index >= list.size()) { 1940 index = CommandParameter.NO_INDEX; 1941 } 1942 1943 if (parent == ((EObject) data).eContainer()) { 1944 if (parent instanceof MElementContainer<?> && data instanceof MUIElement) { 1945 Util.moveElementByIndex(domain, (MUIElement) data, isLiveModel(), index); 1946 } else { 1947 final Command cmd = MoveCommand.create(domain, parent, feature, data, index); 1948 if (cmd.canExecute()) { 1949 domain.getCommandStack().execute(cmd); 1950 return true; 1951 } 1952 } 1953 } else { 1954 // Moving between different sources is always a copy 1955 if (parent.eResource() != ((EObject) data).eResource()) { 1956 data = EcoreUtil.copy((EObject) data); 1957 } 1958 1959 final Command cmd = createRemoveAddCommand(data, feature, parent, index); 1960 if (cmd.canExecute()) { 1961 domain.getCommandStack().execute(cmd); 1962 if (isLiveModel()) { 1963 if (parent instanceof MElementContainer<?> && data instanceof MUIElement) { 1964 ((MElementContainer<MUIElement>) parent).setSelectedElement((MUIElement) data); 1965 } 1966 } 1967 1968 return true; 1969 } 1970 } 1971 } 1972 } 1973 1974 return false; 1975 } 1976 1977 /** 1978 * Create an internal Compound command containing a Remove and a Add so as to 1979 * allow the Undo 1980 * 1981 * @param data the object to be dragged and dropped 1982 * @param destFeature the target feature in the model where data must be dropped 1983 * @param parent the destination parent 1984 * @param index the index in the parent list 1985 * @see bug 429684 1986 * @return the compound command 1987 */ createRemoveAddCommand(Object data, EStructuralFeature destFeature, EObject parent, int index)1988 private Command createRemoveAddCommand(Object data, EStructuralFeature destFeature, EObject parent, int index) { 1989 1990 // Remark : this code could be replaced by a MoveCommand, but unfortunately I 1991 // could not make it working (its canExecute() method always returns false 1992 // because it is not prepared (see canExecute())...)... 1993 1994 List<Command> listOfCommands = new ArrayList<>(); 1995 EStructuralFeature sourceFeature = null; 1996 if (data instanceof EObject) { 1997 sourceFeature = ((EObject) data).eContainmentFeature(); 1998 } 1999 Command removeCommand = RemoveCommand.create(domain, ((EObject) data).eContainer(), sourceFeature, data); 2000 if (removeCommand.canExecute()) { 2001 listOfCommands.add(removeCommand); 2002 } 2003 2004 Command addCommand = AddCommand.create(domain, parent, destFeature, data, index); 2005 listOfCommands.add(addCommand); 2006 CompoundCommand compoundCommand = new CompoundCommand(listOfCommands); 2007 compoundCommand.setLabel(messages.ModelEditor_Move + " " + getObjectNameForCommand(data)); //$NON-NLS-1$ 2008 return compoundCommand; 2009 2010 } 2011 2012 @Override validateDrop(Object target, int operation, TransferData transferType)2013 public boolean validateDrop(Object target, int operation, TransferData transferType) { 2014 boolean rv = true; 2015 if (getSelectedObject() instanceof MApplicationElement || getSelectedObject() instanceof MModelFragment) { 2016 if (getCurrentLocation() == LOCATION_ON) { 2017 rv = isValidTarget(target, getSelectedObject(), false); 2018 } else if (getCurrentLocation() == LOCATION_AFTER || getCurrentLocation() == LOCATION_BEFORE) { 2019 TreeItem item = (TreeItem) getCurrentEvent().item; 2020 if (item != null) { 2021 item = item.getParentItem(); 2022 if (item != null) { 2023 rv = isValidTarget(item.getData(), getSelectedObject(), true); 2024 } 2025 } 2026 } 2027 } 2028 2029 return rv; 2030 } 2031 2032 } 2033 2034 /** 2035 * This method checks if the target object is a valid target for the current 2036 * instance. It used both for paste and for drag and drop behavior 2037 * 2038 * @param target the target object where instance should be pasted of dropped 2039 * @param instance the instance of object to be pasted or dropped 2040 * @param isIndex if true, means that target is an object in a container 2041 * @return 2042 */ isValidTarget(Object target, Object instance, boolean isIndex)2043 private boolean isValidTarget(Object target, Object instance, boolean isIndex) { 2044 if (target instanceof MElementContainer<?>) { 2045 @SuppressWarnings("unchecked") 2046 final MElementContainer<MUIElement> container = (MElementContainer<MUIElement>) target; 2047 2048 if (isIndex || !container.getChildren().contains(instance)) { 2049 final EClassifier classifier = ModelUtils.getTypeArgument(((EObject) container).eClass(), 2050 UiPackageImpl.Literals.ELEMENT_CONTAINER__CHILDREN.getEGenericType()); 2051 return classifier.isInstance(instance); 2052 } 2053 } else if (target instanceof VirtualEntry) { 2054 @SuppressWarnings("unchecked") 2055 final VirtualEntry<EObject, ?> vTarget = (VirtualEntry<EObject, ?>) target; 2056 if (isIndex || !vTarget.getList().contains(instance)) { 2057 if (vTarget.getProperty() instanceof IEMFProperty) { 2058 final EStructuralFeature feature = ((IEMFProperty) vTarget.getProperty()).getStructuralFeature(); 2059 final EObject parent = vTarget.getOriginalParent(); 2060 final EClassifier classifier = ModelUtils.getTypeArgument(parent.eClass(), 2061 feature.getEGenericType()); 2062 return classifier.isInstance(instance); 2063 } 2064 2065 } 2066 } else if (target instanceof EObject) { 2067 final EObject eObj = (EObject) target; 2068 for (final EStructuralFeature f : eObj.eClass().getEAllStructuralFeatures()) { 2069 final EClassifier cl = ModelUtils.getTypeArgument(eObj.eClass(), f.getEGenericType()); 2070 if (cl.isInstance(instance)) { 2071 return true; 2072 } 2073 } 2074 } 2075 2076 return false; 2077 } 2078 2079 /** 2080 * compute a valid name for the undo/redo/paste of move commands 2081 * 2082 * @param data the object concerned by the command 2083 * @return a representative string for the object or 'Object' if nothing found 2084 */ getObjectNameForCommand(Object data)2085 private String getObjectNameForCommand(Object data) { 2086 String clname = (data instanceof ApplicationElementImpl) ? ((ApplicationElementImpl) data).eClass().getName() 2087 : "Object"; //$NON-NLS-1$ 2088 String dname = (data instanceof MUILabel) ? ((MUILabel) data).getLabel() : ""; //$NON-NLS-1$ 2089 return clname + " " + dname; //$NON-NLS-1$ 2090 } 2091 2092 @Override gotoEObject(int targetHint, EObject object)2093 public void gotoEObject(int targetHint, EObject object) { 2094 if (object == null) { 2095 // do nothing 2096 } else { 2097 switch (targetHint) { 2098 case TAB_FORM: 2099 // make sure tree node has been instantiated 2100 final ObservableListTreeContentProvider<?> provider = (ObservableListTreeContentProvider<?>) viewer 2101 .getContentProvider(); 2102 getFirstMatchingItem(object, provider, provider.getChildren(viewer.getInput())); 2103 2104 viewer.reveal(object); 2105 viewer.setSelection(new StructuredSelection(object)); 2106 editorTabFolder.setSelection(getTabIndex(tabItemTree)); 2107 break; 2108 case TAB_XMI: 2109 editorTabFolder.setSelection(getTabIndex(tabItemXmi)); 2110 // model was not updating in XMI document (selection listener 2111 // was not firing from programmatic setSelection() 2112 emfDocumentProvider.updateFromEMF(); 2113 2114 try { 2115 xmiTab.gotoEObject(object); 2116 } catch (final Exception e) { 2117 e.printStackTrace(); 2118 } 2119 break; 2120 case TAB_LIST: 2121 if (tabItemList != null && listTab != null) { 2122 editorTabFolder.setSelection(getTabIndex(tabItemList)); 2123 listTab.getViewer().setSelection(new StructuredSelection(object), true); 2124 } 2125 break; 2126 default: 2127 break; 2128 } 2129 } 2130 } 2131 2132 // This will ensure the provider has created the tree node (so we can reveal 2133 // it). getFirstMatchingItem(EObject target, ObservableListTreeContentProvider<?> provider, Object[] items)2134 private static Object getFirstMatchingItem(EObject target, ObservableListTreeContentProvider<?> provider, 2135 Object[] items) { 2136 for (int i = 0; i < items.length; i++) { 2137 if (items[i] == target) { 2138 return items[i]; 2139 } 2140 final Object found = getFirstMatchingItem(target, provider, provider.getChildren(items[i])); 2141 if (found != null) { 2142 return found; 2143 } 2144 } 2145 return null; 2146 } 2147 refreshViewer()2148 public void refreshViewer() { 2149 viewer.refresh(true); 2150 } 2151 2152 @Inject 2153 @Optional refreshOnSave(@IEventTopicUIEvents.Dirtyable.TOPIC_DIRTY) org.osgi.service.event.Event event, @Named(IServiceConstants.ACTIVE_PART) MPart part)2154 public void refreshOnSave(@UIEventTopic(UIEvents.Dirtyable.TOPIC_DIRTY) org.osgi.service.event.Event event, 2155 @Named(IServiceConstants.ACTIVE_PART) MPart part) { 2156 // If the application model is saved (-> becomes undirty) we must 2157 // refresh tree (bug 472706) 2158 // Must react only if editor is the current one... (bug 509598) 2159 if (part != currentPart) { 2160 return; 2161 } 2162 2163 final Object type = event.getProperty(EventTags.TYPE); 2164 final Object newValue = event.getProperty(EventTags.NEW_VALUE); 2165 2166 if (UIEvents.EventTypes.SET.equals(type) && Boolean.FALSE.equals(newValue) && viewer != null) { 2167 viewer.refresh(true); 2168 } 2169 2170 } 2171 2172 } 2173