1: using System;
2: using System.Collections.ObjectModel;
3: using Microsoft.VisualStudio.Modeling;
4: using Microsoft.VisualStudio.Modeling.Diagrams;
5: using Microsoft.VisualStudio.Modeling.Shell;
6:
7: namespace MyDSL.UserInterface
8: {
9: /// <summary>
10: /// Custom behavior for UserInterfaceModelExplorer.
11: /// </summary>
12: internal partial class UserInterfaceModelExplorer
13: {
14: #region Public Methods
15:
16: /// <summary>
17: /// Executed when the model explorer creates the tree element visitor.
18: /// </summary>
19: /// <returns>The tree element visitor.</returns>
20: protected override IElementVisitor CreateElementVisitor()
21: {
22: // Subscribe double click in the tree view
23:
24: this.ObjectModelBrowser.DoubleClick += new EventHandler(this.ObjectModelBrowser_DoubleClick);
25:
26: // Default behavior
27:
28: return base.CreateElementVisitor();
29: }
30:
31: #endregion
32:
33: #region Private Methods
34:
35: /// <summary>
36: /// Selects the specified shape using the given modeling document data.
37: /// </summary>
38: /// <param name="shapeElement">The shape element that should be selected.</param>
39: /// <param name="docData">The modeling document data.</param>
40: private static void SelectShape(ShapeElement shapeElement, DocData docData)
41: {
42: // Validation
43:
44: if (shapeElement == null)
45: {
46: throw new ArgumentNullException("shapeElement");
47: }
48:
49: if (docData == null)
50: {
51: throw new ArgumentNullException("docData");
52: }
53:
54: // Select the shape
55:
56: ModelingDocView docView = docData.DocViews[0];
57: if (docView != null)
58: {
59: docView.SelectObjects(1, new object[] { shapeElement }, 0);
60: }
61: }
62:
63: /// <summary>
64: /// Gets the first shape the represents the specified model element.
65: /// </summary>
66: /// <param name="modelElement">The model element whose shape will be returned.</param>
67: /// <returns>The first shape the represents the specified model element.</returns>
68: private static ShapeElement GetModelElementFirstShape(ModelElement modelElement)
69: {
70: // Presentation elements
71:
72: LinkedElementCollection<PresentationElement> presentations = PresentationViewsSubject.GetPresentation(modelElement);
73: foreach (ModelElement element in presentations)
74: {
75: ShapeElement shapeElement = (element as ShapeElement);
76: if (shapeElement != null)
77: {
78: return shapeElement;
79: }
80: }
81:
82: // Default result
83:
84: return null;
85: }
86:
87: /// <summary>
88: /// Return the model element which is the parent of the specified model element considering that
89: /// this element is placed in a compartment.
90: /// </summary>
91: /// <param name="modelElement">The model element whose parent will be returned.</param>
92: /// <returns>
93: /// The model element which is the parent of the specified model element considering that
94: /// this element is placed in a compartment.
95: /// </returns>
96: private static ModelElement GetCompartmentElementFirstParent(ModelElement modelElement)
97: {
98: // Get the domain class associated with model element.
99:
100: DomainClassInfo domainClass = modelElement.GetDomainClass();
101: if (domainClass != null)
102: {
103: // A element is only considered to be in a compartment if it participates in only 1 embedding relationship
104: // This might be wrong for some models
105:
106: if (domainClass.AllEmbeddedByDomainRoles.Count == 1)
107: {
108: // Get a collection of all the links to this model element
109: // Since this is in a compartment there will only be one
110:
111: ReadOnlyCollection<ElementLink> links = DomainRoleInfo.GetAllElementLinks(modelElement);
112: if (links.Count == 1)
113: {
114: // Get the model element participating in the link that isn't the current one
115: // That will be the parent
116: // Probably there is a better way to achieve the same result
117:
118: foreach (ModelElement linkedElement in links[0].LinkedElements)
119: {
120: if (!modelElement.Equals(linkedElement))
121: {
122: return linkedElement;
123: }
124: }
125: }
126: }
127: }
128:
129: // Default result
130:
131: return null;
132: }
133:
134: #endregion
135:
136: #region Event Handlers
137:
138: private void ObjectModelBrowser_DoubleClick(object sender, EventArgs e)
139: {
140: // Get the node selected in the model explorer tree
141:
142: ModelElementTreeNode node = (this.ObjectModelBrowser.SelectedNode as ModelElementTreeNode);
143: if (node != null)
144: {
145: // Get the corresponding model element
146:
147: ModelElement element = node.ModelElement;
148: if (element != null)
149: {
150: // Get the corresponding shape
151: // If the model element is in a compartment the result will be null
152:
153: ShapeElement shape = GetModelElementFirstShape(element);
154: if (shape == null)
155: {
156: // If the element is in a compartment, try to get the parent model element to select that
157:
158: ModelElement parentElement = GetCompartmentElementFirstParent(element);
159: if (parentElement != null)
160: {
161: // Get the corresponding shape
162:
163: shape = GetModelElementFirstShape(parentElement);
164: }
165: }
166:
167: // Select the shape
168:
169: if (shape != null)
170: {
171: SelectShape(shape, this.ModelingDocData);
172: }
173: }
174: }
175: }
176:
177: #endregion
178: }
179: }