| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| FigClassifierBox |
|
| 3.0869565217391304;3.087 |
| 1 | /* $Id: FigClassifierBox.java 17739 2010-01-09 08:39:10Z bobtarling $ | |
| 2 | ******************************************************************************* | |
| 3 | * Copyright (c) 2010 Contributors - see below | |
| 4 | * All rights reserved. This program and the accompanying materials | |
| 5 | * are made available under the terms of the Eclipse Public License v1.0 | |
| 6 | * which accompanies this distribution, and is available at | |
| 7 | * http://www.eclipse.org/legal/epl-v10.html | |
| 8 | * | |
| 9 | * Contributors: | |
| 10 | * Bob Tarling | |
| 11 | * Michiel van der Wulp | |
| 12 | ******************************************************************************* | |
| 13 | * | |
| 14 | * Some portions of this file were previously release using the BSD License: | |
| 15 | */ | |
| 16 | // $Id: FigClassifierBox.java 17739 2010-01-09 08:39:10Z bobtarling $ | |
| 17 | // Copyright (c) 1996-2009 The Regents of the University of California. All | |
| 18 | // Rights Reserved. Permission to use, copy, modify, and distribute this | |
| 19 | // software and its documentation without fee, and without a written | |
| 20 | // agreement is hereby granted, provided that the above copyright notice | |
| 21 | // and this paragraph appear in all copies. This software program and | |
| 22 | // documentation are copyrighted by The Regents of the University of | |
| 23 | // California. The software program and documentation are supplied "AS | |
| 24 | // IS", without any accompanying services from The Regents. The Regents | |
| 25 | // does not warrant that the operation of the program will be | |
| 26 | // uninterrupted or error-free. The end-user understands that the program | |
| 27 | // was developed for research purposes and is advised not to rely | |
| 28 | // exclusively on the program for any reason. IN NO EVENT SHALL THE | |
| 29 | // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | |
| 30 | // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | |
| 31 | // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | |
| 32 | // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF | |
| 33 | // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY | |
| 34 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
| 35 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE | |
| 36 | // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF | |
| 37 | // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, | |
| 38 | // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
| 39 | ||
| 40 | package org.argouml.uml.diagram.static_structure.ui; | |
| 41 | ||
| 42 | import java.awt.Rectangle; | |
| 43 | import java.awt.event.MouseEvent; | |
| 44 | import java.beans.PropertyChangeEvent; | |
| 45 | import java.util.HashSet; | |
| 46 | import java.util.Iterator; | |
| 47 | import java.util.List; | |
| 48 | import java.util.Set; | |
| 49 | import java.util.Vector; | |
| 50 | ||
| 51 | import javax.swing.Action; | |
| 52 | ||
| 53 | import org.argouml.model.AddAssociationEvent; | |
| 54 | import org.argouml.model.AssociationChangeEvent; | |
| 55 | import org.argouml.model.AttributeChangeEvent; | |
| 56 | import org.argouml.model.Model; | |
| 57 | import org.argouml.model.RemoveAssociationEvent; | |
| 58 | import org.argouml.model.UmlChangeEvent; | |
| 59 | import org.argouml.ui.ActionCreateContainedModelElement; | |
| 60 | import org.argouml.ui.ArgoJMenu; | |
| 61 | import org.argouml.uml.diagram.DiagramSettings; | |
| 62 | import org.argouml.uml.diagram.OperationsCompartmentContainer; | |
| 63 | import org.argouml.uml.diagram.ui.ActionAddNote; | |
| 64 | import org.argouml.uml.diagram.ui.ActionCompartmentDisplay; | |
| 65 | import org.argouml.uml.diagram.ui.ActionEdgesDisplay; | |
| 66 | import org.argouml.uml.diagram.ui.FigAttributesCompartment; | |
| 67 | import org.argouml.uml.diagram.ui.FigCompartment; | |
| 68 | import org.argouml.uml.diagram.ui.FigCompartmentBox; | |
| 69 | import org.argouml.uml.diagram.ui.FigOperationsCompartment; | |
| 70 | import org.tigris.gef.base.Editor; | |
| 71 | import org.tigris.gef.base.Globals; | |
| 72 | import org.tigris.gef.base.Selection; | |
| 73 | import org.tigris.gef.presentation.Fig; | |
| 74 | ||
| 75 | /** | |
| 76 | * Class to display graphics for any UML Classifier in a diagram.<p> | |
| 77 | * | |
| 78 | * This abstract Fig adds an Operations compartment. | |
| 79 | */ | |
| 80 | public abstract class FigClassifierBox extends FigCompartmentBox | |
| 81 | implements OperationsCompartmentContainer { | |
| 82 | ||
| 83 | /** | |
| 84 | * The Fig for the operations compartment (if any). | |
| 85 | */ | |
| 86 | private FigOperationsCompartment operationsFigCompartment; | |
| 87 | ||
| 88 | private Rectangle getDefaultBounds() { | |
| 89 | // this rectangle marks the operation section; all operations | |
| 90 | // are inside it | |
| 91 | 0 | Rectangle bounds = new Rectangle(DEFAULT_COMPARTMENT_BOUNDS); |
| 92 | // 2nd compartment, so adjust Y appropriately | |
| 93 | 0 | bounds.y = DEFAULT_COMPARTMENT_BOUNDS.y + ROWHEIGHT + 1; |
| 94 | 0 | return bounds; |
| 95 | } | |
| 96 | ||
| 97 | /** | |
| 98 | * Construct a Fig with owner, bounds, and settings. | |
| 99 | * | |
| 100 | * @param owner the model element that owns this fig | |
| 101 | * @param bounds the rectangle defining the bounds | |
| 102 | * @param settings the rendering settings | |
| 103 | */ | |
| 104 | public FigClassifierBox(Object owner, Rectangle bounds, | |
| 105 | DiagramSettings settings) { | |
| 106 | 0 | super(owner, bounds, settings); |
| 107 | 0 | operationsFigCompartment = new FigOperationsCompartment( |
| 108 | owner, | |
| 109 | getDefaultBounds(), | |
| 110 | getSettings()); | |
| 111 | 0 | } |
| 112 | ||
| 113 | /* | |
| 114 | * @see java.lang.Object#clone() | |
| 115 | */ | |
| 116 | public Object clone() { | |
| 117 | 0 | FigClassifierBox figClone = (FigClassifierBox) super.clone(); |
| 118 | 0 | Iterator thisIter = this.getFigs().iterator(); |
| 119 | 0 | while (thisIter.hasNext()) { |
| 120 | 0 | Fig thisFig = (Fig) thisIter.next(); |
| 121 | 0 | if (thisFig == operationsFigCompartment) { |
| 122 | 0 | figClone.operationsFigCompartment = (FigOperationsCompartment) thisFig; |
| 123 | 0 | return figClone; |
| 124 | } | |
| 125 | 0 | } |
| 126 | 0 | return figClone; |
| 127 | } | |
| 128 | ||
| 129 | /** | |
| 130 | * @deprecated by Bob Tarling in 0.29.3 use | |
| 131 | * updateCompartment(Model.getMetaTypes().getAttribute()) | |
| 132 | */ | |
| 133 | protected void updateOperations() { | |
| 134 | 0 | if (!isOperationsVisible()) { |
| 135 | 0 | return; |
| 136 | } | |
| 137 | 0 | operationsFigCompartment.populate(); |
| 138 | ||
| 139 | 0 | setBounds(getBounds()); |
| 140 | 0 | damage(); |
| 141 | 0 | } |
| 142 | ||
| 143 | /* | |
| 144 | * @see org.argouml.uml.diagram.ui.FigNodeModelElement#renderingChanged() | |
| 145 | */ | |
| 146 | public void renderingChanged() { | |
| 147 | 0 | super.renderingChanged(); |
| 148 | // TODO: We should be able to just call renderingChanged on the child | |
| 149 | // figs here instead of doing an updateOperations... | |
| 150 | 0 | updateOperations(); |
| 151 | ||
| 152 | // TODO: Taken from FigClassifierBoxWithAttribute to handle events | |
| 153 | // on an attribute. All this event handling should eventually be moved | |
| 154 | // to the compartment Fig for attributes | |
| 155 | 0 | if (isAttributesVisible()) { |
| 156 | // TODO: We shouldn't actually have to do all this work | |
| 157 | 0 | updateCompartment(Model.getMetaTypes().getAttribute()); |
| 158 | } | |
| 159 | 0 | } |
| 160 | ||
| 161 | /** | |
| 162 | * We are getting events we don't want. Filter them out. | |
| 163 | * TODO: Can we instruct the model event pump not to send these in the | |
| 164 | * first place? See defect 5095. | |
| 165 | * @param event the event | |
| 166 | */ | |
| 167 | public void propertyChange(PropertyChangeEvent event) { | |
| 168 | 0 | if (event.getPropertyName().equals("generalization") |
| 169 | && Model.getFacade().isAGeneralization(event.getOldValue())) { | |
| 170 | 0 | return; |
| 171 | 0 | } else if (event.getPropertyName().equals("association") |
| 172 | && Model.getFacade().isAAssociationEnd(event.getOldValue())) { | |
| 173 | 0 | return; |
| 174 | 0 | } else if (event.getPropertyName().equals("supplierDependency") |
| 175 | && Model.getFacade().isAUsage(event.getOldValue())) { | |
| 176 | 0 | return; |
| 177 | 0 | } else if (event.getPropertyName().equals("clientDependency") |
| 178 | && Model.getFacade().isAAbstraction(event.getOldValue())) { | |
| 179 | 0 | return; |
| 180 | } | |
| 181 | ||
| 182 | 0 | super.propertyChange(event); |
| 183 | 0 | } |
| 184 | ||
| 185 | protected void updateLayout(UmlChangeEvent event) { | |
| 186 | 0 | super.updateLayout(event); |
| 187 | 0 | if (event instanceof AssociationChangeEvent |
| 188 | && getOwner().equals(event.getSource())) { | |
| 189 | 0 | Object o = null; |
| 190 | 0 | if (event instanceof AddAssociationEvent) { |
| 191 | 0 | o = event.getNewValue(); |
| 192 | 0 | } else if (event instanceof RemoveAssociationEvent) { |
| 193 | 0 | o = event.getOldValue(); |
| 194 | } | |
| 195 | 0 | if (Model.getFacade().isAOperation(o) |
| 196 | || Model.getFacade().isAReception(o)) { | |
| 197 | 0 | updateOperations(); |
| 198 | } | |
| 199 | } | |
| 200 | ||
| 201 | // TODO: Taken from FigClassifierBoxWithAttribute to handle events | |
| 202 | // on an attribute. All this event handling should eventually be moved | |
| 203 | // to the compartment Fig for attributes | |
| 204 | 0 | if (Model.getFacade().isAAttribute(getOwner())) { |
| 205 | 0 | if (event instanceof AttributeChangeEvent) { |
| 206 | 0 | Object source = event.getSource(); |
| 207 | 0 | if (Model.getFacade().isAAttribute(source)) { |
| 208 | // TODO: We just need to get someone to re-render a single | |
| 209 | // line of text which represents the element here, but I'm | |
| 210 | // not sure how to do that. - tfm | |
| 211 | // TODO: Bob replies - we shouldn't be interested in this | |
| 212 | // event here. The FigFeature (or its notation) should be | |
| 213 | // listen for change and the FigFeature should be update | |
| 214 | // from that. | |
| 215 | 0 | updateCompartment(Model.getMetaTypes().getAttribute()); |
| 216 | } | |
| 217 | 0 | } else if (event instanceof AssociationChangeEvent |
| 218 | && getOwner().equals(event.getSource())) { | |
| 219 | 0 | Object o = null; |
| 220 | 0 | if (event instanceof AddAssociationEvent) { |
| 221 | 0 | o = event.getNewValue(); |
| 222 | 0 | } else if (event instanceof RemoveAssociationEvent) { |
| 223 | 0 | o = event.getOldValue(); |
| 224 | } | |
| 225 | 0 | if (Model.getFacade().isAAttribute(o)) { |
| 226 | // TODO: Bob says - we should not be listening here for | |
| 227 | // addition and removal of attributes. This should be done in | |
| 228 | // FigAttributesCompartment. | |
| 229 | 0 | updateCompartment(Model.getMetaTypes().getAttribute()); |
| 230 | } | |
| 231 | } | |
| 232 | } | |
| 233 | 0 | } |
| 234 | ||
| 235 | @Override | |
| 236 | protected void updateListeners(Object oldOwner, Object newOwner) { | |
| 237 | ||
| 238 | 0 | if (isAttributesVisible()) { |
| 239 | 0 | Set<Object[]> listeners = new HashSet<Object[]>(); |
| 240 | ||
| 241 | // Collect the set of model elements that we want to listen to | |
| 242 | 0 | if (newOwner != null) { |
| 243 | // TODO: Because we get called on each and every change event, when | |
| 244 | // the model is in a state of flux, we'll often get an | |
| 245 | // InvalidElementException before we finish this collection. The | |
| 246 | // only saving grace is that we're called SO many times that on the | |
| 247 | // last time, things should be stable again and we'll get a good set | |
| 248 | // of elements for the final update. We need a better mechanism. | |
| 249 | ||
| 250 | // add the listeners to the newOwner | |
| 251 | 0 | listeners.add(new Object[] {newOwner, null}); |
| 252 | ||
| 253 | // and its stereotypes | |
| 254 | // TODO: Aren't stereotypes handled elsewhere? | |
| 255 | for (Object stereotype | |
| 256 | 0 | : Model.getFacade().getStereotypes(newOwner)) { |
| 257 | 0 | listeners.add(new Object[] {stereotype, null}); |
| 258 | } | |
| 259 | ||
| 260 | // and its features | |
| 261 | 0 | for (Object feat : Model.getFacade().getFeatures(newOwner)) { |
| 262 | 0 | listeners.add(new Object[] {feat, null}); |
| 263 | // and the stereotypes of its features | |
| 264 | for (Object stereotype | |
| 265 | 0 | : Model.getFacade().getStereotypes(feat)) { |
| 266 | 0 | listeners.add(new Object[] {stereotype, null}); |
| 267 | } | |
| 268 | // and the parameter of its operations | |
| 269 | 0 | if (Model.getFacade().isAOperation(feat)) { |
| 270 | 0 | for (Object param : Model.getFacade().getParameters(feat)) { |
| 271 | 0 | listeners.add(new Object[] {param, null}); |
| 272 | } | |
| 273 | } | |
| 274 | } | |
| 275 | } | |
| 276 | ||
| 277 | // Update the listeners to match the desired set using the minimal | |
| 278 | // update facility | |
| 279 | 0 | updateElementListeners(listeners); |
| 280 | 0 | } else { |
| 281 | 0 | super.updateListeners(oldOwner, newOwner); |
| 282 | } | |
| 283 | 0 | } |
| 284 | ||
| 285 | /** | |
| 286 | * Updates a compartment box. Called from updateLayout if there is | |
| 287 | * a model event effecting the attributes/operations and from | |
| 288 | * renderingChanged in all cases. | |
| 289 | * TODO: The above statement means that the entire contents of the | |
| 290 | * compartments are being rebuilt whenever an add/remove | |
| 291 | * of an attribute, operation or a reception is detected. It would be | |
| 292 | * better to have compartments listen for add and remove events | |
| 293 | * and make minimum change rather than entirely rebuild. | |
| 294 | * Remark MVW: This is a bit exaggerated, since the populate() | |
| 295 | * method is already heavily optimized. | |
| 296 | */ | |
| 297 | protected void updateCompartment(Object metaType) { | |
| 298 | 0 | FigCompartment fc = getCompartment(metaType); |
| 299 | 0 | if (!fc.isVisible()) { |
| 300 | 0 | return; |
| 301 | } | |
| 302 | 0 | fc.populate(); |
| 303 | ||
| 304 | // TODO: make setBounds, calcBounds and updateBounds consistent | |
| 305 | 0 | setBounds(getBounds()); |
| 306 | 0 | } |
| 307 | ||
| 308 | /** | |
| 309 | * @return The graphics for the UML operations (if any). | |
| 310 | * @deprecated in 0.29.3 use | |
| 311 | * getCompartment(Model.getUmlFactory(Model.getMetaTypes(),getOperation())) | |
| 312 | * to determine if an operation compartment exists and return it. | |
| 313 | * The operationsCompartment should be created by the concrete class | |
| 314 | */ | |
| 315 | protected FigOperationsCompartment getOperationsFig() { | |
| 316 | 0 | return operationsFigCompartment; |
| 317 | } | |
| 318 | ||
| 319 | /** | |
| 320 | * @deprecated by Bob Tarling in 0.29.3 use | |
| 321 | * getCompartment(Model.getMetaTypes().getOperation()).getBounds() | |
| 322 | * @return the bounds | |
| 323 | */ | |
| 324 | public Rectangle getOperationsBounds() { | |
| 325 | 0 | return operationsFigCompartment.getBounds(); |
| 326 | } | |
| 327 | ||
| 328 | /** | |
| 329 | * @deprecated by Bob Tarling in 0.29.2 use | |
| 330 | * isCompartmentVisible(Model.getMetaTypes().getOperation()) | |
| 331 | * @return the visibility | |
| 332 | */ | |
| 333 | public boolean isOperationsVisible() { | |
| 334 | 0 | return operationsFigCompartment != null && operationsFigCompartment.isVisible(); |
| 335 | } | |
| 336 | ||
| 337 | /** | |
| 338 | * TODO: Should not be on this class as we don't know if we'll have | |
| 339 | * operations | |
| 340 | * @param isVisible true if the operation compartment is visible | |
| 341 | * @deprecated by Bob Tarling in 0.29.2 use setCompartmentVisible | |
| 342 | */ | |
| 343 | public void setOperationsVisible(boolean isVisible) { | |
| 344 | 0 | setCompartmentVisible(operationsFigCompartment, isVisible); |
| 345 | 0 | } |
| 346 | ||
| 347 | /** | |
| 348 | * @return The graphics for the UML attributes (if any). | |
| 349 | * @deprecated in 0.29.1 use | |
| 350 | * getCompartment(Model.getUmlFactory(Model.getMetaTypes(),getAttribute())) | |
| 351 | * to determine if an attribute compartment exists and return it. | |
| 352 | * The attributesCompartment should be created by the concrete class | |
| 353 | */ | |
| 354 | protected FigAttributesCompartment getAttributesFig() { | |
| 355 | 0 | FigCompartment fc = getCompartment(Model.getMetaTypes().getAttribute()); |
| 356 | 0 | return (FigAttributesCompartment) fc; |
| 357 | } | |
| 358 | ||
| 359 | /** | |
| 360 | * @deprecated by Bob Tarling in 0.29.2 use | |
| 361 | * getCompartment(Model.getMetaTypes().getAttribute()).getBounds() | |
| 362 | * @return the bounds | |
| 363 | */ | |
| 364 | @Deprecated | |
| 365 | public Rectangle getAttributesBounds() { | |
| 366 | 0 | return getAttributesFig().getBounds(); |
| 367 | } | |
| 368 | ||
| 369 | /** | |
| 370 | * @deprecated by Bob Tarling in 0.29.2 use | |
| 371 | * isCompartmentVisible(Model.getMetaTypes().getAttribute()) | |
| 372 | * @return the visibility | |
| 373 | */ | |
| 374 | @Deprecated | |
| 375 | public boolean isAttributesVisible() { | |
| 376 | 0 | FigCompartment fc = getCompartment(Model.getMetaTypes().getAttribute()); |
| 377 | 0 | return fc != null && fc.isVisible(); |
| 378 | } | |
| 379 | ||
| 380 | /** | |
| 381 | * TODO: Should not be on this class as we don't know if we'll have | |
| 382 | * attributes | |
| 383 | * @param isVisible true if the attribute compartment is visible | |
| 384 | * @deprecated by Bob Tarling in 0.29.2 use setCompartmentVisible | |
| 385 | */ | |
| 386 | public void setAttributesVisible(boolean isVisible) { | |
| 387 | 0 | final FigCompartment afc = |
| 388 | getCompartment(Model.getMetaTypes().getAttribute()); | |
| 389 | 0 | setCompartmentVisible(afc, isVisible); |
| 390 | 0 | } |
| 391 | ||
| 392 | /* | |
| 393 | * @see org.tigris.gef.presentation.Fig#translate(int, int) | |
| 394 | */ | |
| 395 | public void translate(int dx, int dy) { | |
| 396 | 0 | super.translate(dx, dy); |
| 397 | 0 | Editor ce = Globals.curEditor(); |
| 398 | 0 | if (ce != null) { |
| 399 | 0 | Selection sel = ce.getSelectionManager().findSelectionFor(this); |
| 400 | // TODO" What is the purpose of this? Why do we hide buttons here? | |
| 401 | // Presumably if so we should not assume SelectionClass | |
| 402 | 0 | if (sel instanceof SelectionClass) { |
| 403 | 0 | ((SelectionClass) sel).hideButtons(); |
| 404 | } | |
| 405 | } | |
| 406 | 0 | } |
| 407 | ||
| 408 | /** | |
| 409 | * Build a collection of menu items relevant for a right-click | |
| 410 | * popup menu on an Interface. | |
| 411 | * | |
| 412 | * @param me a mouse event | |
| 413 | * @return a collection of menu items | |
| 414 | */ | |
| 415 | public Vector getPopUpActions(MouseEvent me) { | |
| 416 | 0 | Vector popUpActions = super.getPopUpActions(me); |
| 417 | ||
| 418 | // Add ... | |
| 419 | 0 | ArgoJMenu addMenu = buildAddMenu(); |
| 420 | 0 | popUpActions.add( |
| 421 | popUpActions.size() - getPopupAddOffset(), | |
| 422 | addMenu); | |
| 423 | ||
| 424 | // Modifier ... | |
| 425 | 0 | popUpActions.add( |
| 426 | popUpActions.size() - getPopupAddOffset(), | |
| 427 | buildModifierPopUp()); | |
| 428 | ||
| 429 | // Visibility ... | |
| 430 | 0 | popUpActions.add( |
| 431 | popUpActions.size() - getPopupAddOffset(), | |
| 432 | buildVisibilityPopUp()); | |
| 433 | ||
| 434 | 0 | return popUpActions; |
| 435 | } | |
| 436 | ||
| 437 | protected ArgoJMenu buildShowPopUp() { | |
| 438 | 0 | ArgoJMenu showMenu = super.buildShowPopUp(); |
| 439 | ||
| 440 | 0 | Iterator i = ActionCompartmentDisplay.getActions().iterator(); |
| 441 | 0 | while (i.hasNext()) { |
| 442 | 0 | showMenu.add((Action) i.next()); |
| 443 | } | |
| 444 | 0 | return showMenu; |
| 445 | } | |
| 446 | ||
| 447 | protected ArgoJMenu buildAddMenu() { | |
| 448 | 0 | ArgoJMenu addMenu = new ArgoJMenu("menu.popup.add"); |
| 449 | ||
| 450 | 0 | List<FigCompartment> comps = getCompartments(); |
| 451 | 0 | for (FigCompartment comp : comps) { |
| 452 | 0 | final Object metaType = comp.getCompartmentType(); |
| 453 | 0 | Action addAction = new ActionCreateContainedModelElement(metaType, getOwner()); |
| 454 | 0 | addAction.setEnabled(isSingleTarget()); |
| 455 | 0 | addMenu.insert(addAction, 0); |
| 456 | 0 | } |
| 457 | 0 | addMenu.add(new ActionAddNote()); |
| 458 | 0 | addMenu.add(ActionEdgesDisplay.getShowEdges()); |
| 459 | 0 | addMenu.add(ActionEdgesDisplay.getHideEdges()); |
| 460 | 0 | return addMenu; |
| 461 | } | |
| 462 | ||
| 463 | /** | |
| 464 | * USED BY PGML.tee. | |
| 465 | * TODO We should loop round the compartments to build this string. That | |
| 466 | * way we have no attribute/operation knowledge at this level. | |
| 467 | * @return the class name and bounds together with compartment | |
| 468 | * visibility. | |
| 469 | */ | |
| 470 | public String classNameAndBounds() { | |
| 471 | 0 | String classNameAndBounds = super.classNameAndBounds() |
| 472 | + "operationsVisible=" + isOperationsVisible() + ";"; | |
| 473 | 0 | FigCompartment fc = getCompartment(Model.getMetaTypes().getAttribute()); |
| 474 | 0 | if (fc != null) { |
| 475 | 0 | classNameAndBounds += |
| 476 | "attributesVisible=" + fc.isVisible() + ";"; | |
| 477 | } | |
| 478 | 0 | return classNameAndBounds; |
| 479 | } | |
| 480 | ||
| 481 | ||
| 482 | protected Object buildModifierPopUp() { | |
| 483 | 0 | return buildModifierPopUp(ABSTRACT | LEAF | ROOT); |
| 484 | } | |
| 485 | } |