Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ProjectManager |
|
| 1.6666666666666667;1.667 | ||||
ProjectManager$1 |
|
| 1.6666666666666667;1.667 | ||||
ProjectManager$2 |
|
| 1.6666666666666667;1.667 | ||||
ProjectManager$3 |
|
| 1.6666666666666667;1.667 |
1 | /* $Id: ProjectManager.java 18968 2011-01-13 14:39:23Z tfmorris $ | |
2 | ***************************************************************************** | |
3 | * Copyright (c) 2009 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 | * thn | |
11 | ***************************************************************************** | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // Copyright (c) 1996-2008 The Regents of the University of California. All | |
17 | // Rights Reserved. Permission to use, copy, modify, and distribute this | |
18 | // software and its documentation without fee, and without a written | |
19 | // agreement is hereby granted, provided that the above copyright notice | |
20 | // and this paragraph appear in all copies. This software program and | |
21 | // documentation are copyrighted by The Regents of the University of | |
22 | // California. The software program and documentation are supplied "AS | |
23 | // IS", without any accompanying services from The Regents. The Regents | |
24 | // does not warrant that the operation of the program will be | |
25 | // uninterrupted or error-free. The end-user understands that the program | |
26 | // was developed for research purposes and is advised not to rely | |
27 | // exclusively on the program for any reason. IN NO EVENT SHALL THE | |
28 | // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | |
29 | // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | |
30 | // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | |
31 | // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF | |
32 | // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY | |
33 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
34 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE | |
35 | // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF | |
36 | // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, | |
37 | // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
38 | ||
39 | package org.argouml.kernel; | |
40 | ||
41 | import java.beans.PropertyChangeEvent; | |
42 | import java.beans.PropertyChangeListener; | |
43 | import java.util.ArrayList; | |
44 | import java.util.Collection; | |
45 | import java.util.LinkedList; | |
46 | import java.util.List; | |
47 | ||
48 | import javax.swing.Action; | |
49 | import javax.swing.event.EventListenerList; | |
50 | ||
51 | import org.apache.log4j.Logger; | |
52 | import org.argouml.application.events.ArgoEventPump; | |
53 | import org.argouml.application.events.ArgoEventTypes; | |
54 | import org.argouml.application.events.ArgoStatusEvent; | |
55 | import org.argouml.cognitive.Designer; | |
56 | import org.argouml.i18n.Translator; | |
57 | import org.argouml.model.Model; | |
58 | import org.argouml.model.ModelCommand; | |
59 | import org.argouml.model.ModelCommandCreationObserver; | |
60 | import org.argouml.profile.Profile; | |
61 | import org.argouml.profile.ProfileException; | |
62 | import org.argouml.uml.cognitive.ProjectMemberTodoList; | |
63 | import org.argouml.uml.diagram.ArgoDiagram; | |
64 | import org.argouml.uml.diagram.DiagramFactory; | |
65 | ||
66 | /** | |
67 | * This class manages the projects loaded in argouml, | |
68 | * and what the current project is. <p> | |
69 | * | |
70 | * Classes in ArgoUML can ask this class for the current | |
71 | * project and set the current project. Since we only have one | |
72 | * project in ArgoUML at the moment, this class does not manage a list | |
73 | * of projects like one would expect. This could be a nice extension | |
74 | * for the future of ArgoUML. As soon as the current project is | |
75 | * changed, a property changed event is fired. <p> | |
76 | * | |
77 | * TODO: Move everything related to the creation of a project | |
78 | * into the ProjectFactory. | |
79 | * | |
80 | * @since Nov 17, 2002 | |
81 | * @author jaap.branderhorst@xs4all.nl | |
82 | * @stereotype singleton | |
83 | */ | |
84 | 4854 | public final class ProjectManager implements ModelCommandCreationObserver { |
85 | ||
86 | /** | |
87 | * The name of the property that defines the current project. The values | |
88 | * passed are Projects, not Strings. The 'name' here refers to the name | |
89 | * of this property, not the name of the project. | |
90 | * | |
91 | * @deprecated for 0.27.2 by tfmorris. Listeners of this event which expect | |
92 | * it to indicate a new project being opened should listen for | |
93 | * {@link #OPEN_PROJECTS_PROPERTY}. Listeners who think | |
94 | * they need to know a single global current project need | |
95 | * to be changed to deal with things on a per-project basis. | |
96 | */ | |
97 | @Deprecated | |
98 | public static final String CURRENT_PROJECT_PROPERTY_NAME = "currentProject"; | |
99 | ||
100 | /** | |
101 | * Property name for list of current open projects. Old and new property | |
102 | * values are of type Project[] (arrays of Projects). | |
103 | */ | |
104 | public static final String OPEN_PROJECTS_PROPERTY = "openProjects"; | |
105 | ||
106 | 900 | private static final Logger LOG = Logger.getLogger(ProjectManager.class); |
107 | ||
108 | /** | |
109 | * The singleton instance of this class. | |
110 | */ | |
111 | 900 | private static ProjectManager instance = new ProjectManager(); |
112 | ||
113 | /** | |
114 | * The project that is visible in the projectbrowser. | |
115 | */ | |
116 | private static Project currentProject; | |
117 | ||
118 | 900 | private static LinkedList<Project> openProjects = new LinkedList<Project>(); |
119 | ||
120 | /** | |
121 | * Flag to indicate we are creating a new current project. | |
122 | * TODO: This isn't a thread-safe way of doing mutual exclusion. | |
123 | */ | |
124 | private boolean creatingCurrentProject; | |
125 | ||
126 | private Action saveAction; | |
127 | ||
128 | /** | |
129 | * The listener list. | |
130 | */ | |
131 | 900 | private EventListenerList listenerList = new EventListenerList(); |
132 | ||
133 | /** | |
134 | * The event to fire. | |
135 | * | |
136 | * TODO: Investigate! Is the purpose really to let the next call to | |
137 | * {@link #firePropertyChanged(String, Object, Object)} fire the old | |
138 | * event again if the previous invocation resulted in an exception? | |
139 | * If so, please document why. If not, fix it. | |
140 | */ | |
141 | private PropertyChangeEvent event; | |
142 | ||
143 | /** | |
144 | * The singleton accessor method of this class. | |
145 | * | |
146 | * @return The singleton. | |
147 | */ | |
148 | public static ProjectManager getManager() { | |
149 | 43211 | return instance; |
150 | } | |
151 | ||
152 | /** | |
153 | * Constructor for ProjectManager. | |
154 | */ | |
155 | private ProjectManager() { | |
156 | 900 | super(); |
157 | 900 | Model.setModelCommandCreationObserver(this); |
158 | 900 | } |
159 | ||
160 | /** | |
161 | * Adds a listener to the listener list. | |
162 | * | |
163 | * @param listener The listener to add. | |
164 | */ | |
165 | public void addPropertyChangeListener(PropertyChangeListener listener) { | |
166 | 3600 | listenerList.add(PropertyChangeListener.class, listener); |
167 | 3600 | } |
168 | ||
169 | /** | |
170 | * Removes a listener from the listener list. | |
171 | * | |
172 | * @param listener The listener to remove. | |
173 | */ | |
174 | public void removePropertyChangeListener(PropertyChangeListener listener) { | |
175 | 0 | listenerList.remove(PropertyChangeListener.class, listener); |
176 | 0 | } |
177 | ||
178 | /** | |
179 | * Fire an event to all members of the listener list. | |
180 | * | |
181 | * @param propertyName The name of the event. | |
182 | * @param oldValue The old value. | |
183 | * @param newValue The new value. | |
184 | */ | |
185 | void firePropertyChanged(String propertyName, | |
186 | Object oldValue, Object newValue) { | |
187 | // Guaranteed to return a non-null array | |
188 | 3774 | Object[] listeners = listenerList.getListenerList(); |
189 | // Process the listeners last to first, notifying | |
190 | // those that are interested in this event | |
191 | 18870 | for (int i = listeners.length - 2; i >= 0; i -= 2) { |
192 | 15096 | if (listeners[i] == PropertyChangeListener.class) { |
193 | // Lazily create the event: | |
194 | 15096 | if (event == null) { |
195 | 3774 | event = |
196 | new PropertyChangeEvent( | |
197 | this, | |
198 | propertyName, | |
199 | oldValue, | |
200 | newValue); | |
201 | } | |
202 | 15096 | ((PropertyChangeListener) listeners[i + 1]).propertyChange( |
203 | event); | |
204 | } | |
205 | } | |
206 | 3774 | event = null; |
207 | 3774 | } |
208 | ||
209 | /** | |
210 | * Sets the current project (the project that is viewable in the | |
211 | * projectbrowser). Sets the current diagram for the project (if one | |
212 | * exists). This method fires a propertychanged event. | |
213 | * <p> | |
214 | * If the argument is null, then the current project will be forgotten | |
215 | * about. | |
216 | * | |
217 | * @param newProject The new project. | |
218 | * @deprecated for 0.27.2 by tfmorris. There is no longer the concept of a | |
219 | * single global "current" project. In the future, multiple | |
220 | * projects will be able to be open at a time, so all code | |
221 | * should be prepared to deal with multiple projects and should | |
222 | * require a Project to be passed as an argument if they need | |
223 | * access. | |
224 | */ | |
225 | public void setCurrentProject(Project newProject) { | |
226 | 1868 | Project oldProject = currentProject; |
227 | 1868 | currentProject = newProject; |
228 | 1868 | addProject(newProject); |
229 | 1868 | if (currentProject != null |
230 | && currentProject.getActiveDiagram() == null) { | |
231 | 0 | List<ArgoDiagram> diagrams = currentProject.getDiagramList(); |
232 | 0 | if (diagrams != null && !diagrams.isEmpty()) { |
233 | 0 | ArgoDiagram activeDiagram = diagrams.get(0); |
234 | 0 | currentProject.setActiveDiagram(activeDiagram); |
235 | } | |
236 | } | |
237 | 1868 | notifyProjectAdded(newProject, oldProject); |
238 | 1868 | } |
239 | ||
240 | private void notifyProjectAdded(Project newProject, Project oldProject) { | |
241 | 1868 | firePropertyChanged(CURRENT_PROJECT_PROPERTY_NAME, |
242 | oldProject, newProject); | |
243 | // TODO: Tentative implementation. Do we want something that updates | |
244 | // the list of open projects or just simple open and close events? -tfm | |
245 | 1868 | firePropertyChanged(OPEN_PROJECTS_PROPERTY, |
246 | new Project[] {oldProject}, new Project[] {newProject}); | |
247 | 1868 | } |
248 | ||
249 | /** | |
250 | * Returns the current project (ie the project which must recently had the | |
251 | * user focus) or null if there is no current project. | |
252 | * <p> | |
253 | * This should only be used by callers who need to know the global state. | |
254 | * Most things which need a project want the project that contains them, | |
255 | * which they can discover by traversing their containing elements (e.g. | |
256 | * Fig->Diagram->DiagramSettings). | |
257 | * <p> | |
258 | * | |
259 | * @return Project the current project or null if none | |
260 | * @deprecated for 0.27.2 by tfmorris. There is no longer the concept of a | |
261 | * single global "current" project. In the future, multiple | |
262 | * projects will be able to be open at a time, so all code | |
263 | * should be prepared to deal with multiple projects and should | |
264 | * require a Project to be passed as an argument if they need | |
265 | * access. To get a list of all currently open projects, use | |
266 | * {@link #getOpenProjects()}. For settings which affect | |
267 | * renderings in diagrams use | |
268 | * {@link org.argouml.uml.diagram.ui.ArgoFig#getSettings()}. | |
269 | */ | |
270 | @Deprecated | |
271 | public Project getCurrentProject() { | |
272 | 35948 | return currentProject; |
273 | } | |
274 | ||
275 | /** | |
276 | * @return a list of the currently open Projects in the order they were | |
277 | * opened | |
278 | */ | |
279 | public List<Project> getOpenProjects() { | |
280 | 0 | List<Project> result = new ArrayList<Project>(); |
281 | 0 | if (currentProject != null) { |
282 | 0 | result.add(currentProject); |
283 | } | |
284 | 0 | return result; |
285 | } | |
286 | ||
287 | /** | |
288 | * Makes an empty project. | |
289 | * @return Project the empty project | |
290 | */ | |
291 | public Project makeEmptyProject() { | |
292 | 54 | return makeEmptyProject(true); |
293 | } | |
294 | ||
295 | /** | |
296 | * Make a new empty project optionally including default diagrams. | |
297 | * <p> | |
298 | * Historically new projects have been created with two default diagrams | |
299 | * (Class and Use Case). NOTE: ArgoUML currently requires at least one | |
300 | * diagram for proper operation. | |
301 | * | |
302 | * @param addDefaultDiagrams | |
303 | * if true the project will be be created with the two standard | |
304 | * default diagrams (Class and Use Case) | |
305 | * @return Project the newly created project | |
306 | */ | |
307 | public Project makeEmptyProject(final boolean addDefaultDiagrams) { | |
308 | 954 | final Command cmd = new NonUndoableCommand() { |
309 | ||
310 | @Override | |
311 | public Object execute() { | |
312 | 954 | Model.getPump().stopPumpingEvents(); |
313 | ||
314 | 954 | creatingCurrentProject = true; |
315 | 954 | LOG.info("making empty project"); |
316 | 954 | Project newProject = new ProjectImpl(); |
317 | 954 | createDefaultModel(newProject); |
318 | 954 | if (addDefaultDiagrams) { |
319 | 954 | createDefaultDiagrams(newProject); |
320 | } | |
321 | 954 | creatingCurrentProject = false; |
322 | 954 | setCurrentProject(newProject); |
323 | 954 | Model.getPump().startPumpingEvents(); |
324 | 954 | return null; |
325 | } | |
326 | }; | |
327 | 954 | cmd.execute(); |
328 | 954 | currentProject.getUndoManager().addCommand(cmd); |
329 | 954 | setSaveEnabled(false); |
330 | 954 | return currentProject; |
331 | } | |
332 | ||
333 | /** | |
334 | * Makes an empty profile project. | |
335 | * @return Project the empty profile project | |
336 | */ | |
337 | public Project makeEmptyProfileProject() { | |
338 | 14 | return makeEmptyProfileProject(true); |
339 | } | |
340 | ||
341 | /** | |
342 | * Make a new empty profile project optionally including default diagrams. | |
343 | * <p> | |
344 | * Historically new projects have been created with two default diagrams | |
345 | * (Class and Use Case). NOTE: ArgoUML currently requires at least one | |
346 | * diagram for proper operation. | |
347 | * | |
348 | * @param addDefaultDiagrams | |
349 | * if true the project will be be created with the standard | |
350 | * default diagram (Class) | |
351 | * @return Project the newly created profile project | |
352 | */ | |
353 | public Project makeEmptyProfileProject(final boolean addDefaultDiagrams) { | |
354 | 14 | final Command cmd = new NonUndoableCommand() { |
355 | ||
356 | @Override | |
357 | public Object execute() { | |
358 | 14 | Model.getPump().stopPumpingEvents(); |
359 | ||
360 | 14 | creatingCurrentProject = true; |
361 | 14 | LOG.info("making empty profile project"); |
362 | 14 | Project newProject = new ProjectImpl(Project.PROFILE_PROJECT); |
363 | 14 | createDefaultProfile(newProject); |
364 | 14 | if (addDefaultDiagrams) { |
365 | 14 | ArgoDiagram d = createClassDiagram(newProject); |
366 | 14 | createTodoList(newProject); |
367 | 14 | newProject.setActiveDiagram(d); |
368 | } | |
369 | 14 | creatingCurrentProject = false; |
370 | 14 | setCurrentProject(newProject); |
371 | 14 | Model.getPump().startPumpingEvents(); |
372 | 14 | return null; |
373 | } | |
374 | }; | |
375 | 14 | cmd.execute(); |
376 | 14 | currentProject.getUndoManager().addCommand(cmd); |
377 | 14 | setSaveEnabled(false); |
378 | 14 | return currentProject; |
379 | } | |
380 | ||
381 | /** | |
382 | * Apply all profiles from the profile configuration to a model (can be a | |
383 | * profile too). | |
384 | * | |
385 | * @param project The project with the profile configuration. | |
386 | * @param model The model to apply the profiles to. | |
387 | */ | |
388 | private void applyProfileConfiguration(Project project, Object model) { | |
389 | 968 | Collection<Profile> c = |
390 | project.getProfileConfiguration().getProfiles(); | |
391 | 968 | if (c != null) { |
392 | 968 | for (Profile p : c) { |
393 | try { | |
394 | 2862 | for (Object profile : p.getProfilePackages()) { |
395 | 954 | Model.getExtensionMechanismsHelper() |
396 | .applyProfile(model, profile); | |
397 | } | |
398 | 0 | } catch (ProfileException pe) { |
399 | 0 | LOG.warn("Failed to get profile packages from profile " |
400 | + p.getDisplayName()); | |
401 | 5724 | } |
402 | } | |
403 | } | |
404 | 968 | } |
405 | ||
406 | /** | |
407 | * Create the default diagrams for the project. Currently a Class Diagram | |
408 | * and a UseCase diagram. | |
409 | * | |
410 | * @param project the project to create the diagrams in. | |
411 | */ | |
412 | private void createDefaultDiagrams(Project project) { | |
413 | 954 | LOG.debug("Creating default diagrams"); |
414 | 954 | Object model = project.getRoots().iterator().next(); |
415 | 954 | DiagramFactory df = DiagramFactory.getInstance(); |
416 | 954 | ArgoDiagram d = createClassDiagram(project); |
417 | 954 | LOG.debug("Creating use case diagram"); |
418 | 954 | project.addMember(df.create( |
419 | DiagramFactory.DiagramType.UseCase, model, | |
420 | project.getProjectSettings().getDefaultDiagramSettings())); | |
421 | 954 | project.addMember(new ProjectMemberTodoList("", |
422 | project)); | |
423 | 954 | createTodoList(project); |
424 | 954 | project.setActiveDiagram(d); |
425 | 954 | } |
426 | ||
427 | /** | |
428 | * Create a class diagrams for the project. | |
429 | * | |
430 | * @param project the project to create the diagram in. | |
431 | * @return the created class diagram | |
432 | */ | |
433 | private ArgoDiagram createClassDiagram(Project project) { | |
434 | 968 | LOG.debug("Creating class diagram"); |
435 | 968 | Object model = project.getRoots().iterator().next(); |
436 | 968 | DiagramFactory df = DiagramFactory.getInstance(); |
437 | 968 | ArgoDiagram d = df.create(DiagramFactory.DiagramType.Class, |
438 | model, | |
439 | project.getProjectSettings().getDefaultDiagramSettings()); | |
440 | 968 | project.addMember(d); |
441 | 968 | return d; |
442 | } | |
443 | ||
444 | /** | |
445 | * Create a todo list for the project. | |
446 | * | |
447 | * @param project the project to create the todo list in. | |
448 | */ | |
449 | private void createTodoList(Project project) { | |
450 | 968 | LOG.debug("Creating todo list"); |
451 | 968 | project.addMember(new ProjectMemberTodoList("", |
452 | project)); | |
453 | 968 | } |
454 | ||
455 | /** | |
456 | * Create the top level model for the project and set it as a root and the | |
457 | * current namespace. | |
458 | * | |
459 | * @param project the project to create the model in. | |
460 | */ | |
461 | private void createDefaultModel(Project project) { | |
462 | 954 | Object model = Model.getModelManagementFactory().createModel(); |
463 | 954 | Model.getCoreHelper().setName(model, |
464 | Translator.localize("misc.untitled-model")); | |
465 | 954 | Collection roots = new ArrayList(); |
466 | 954 | roots.add(model); |
467 | 954 | project.setRoots(roots); |
468 | 954 | project.setCurrentNamespace(model); |
469 | 954 | project.addMember(model); |
470 | // finally, apply profile configuration to the model | |
471 | 954 | applyProfileConfiguration(project, model); |
472 | 954 | } |
473 | ||
474 | /** | |
475 | * Create the top level profile for the project and set it as a root and the | |
476 | * current namespace. | |
477 | * | |
478 | * @param project the project to create the model in. | |
479 | */ | |
480 | private void createDefaultProfile(Project project) { | |
481 | 14 | Object model = Model.getModelManagementFactory().createProfile(); |
482 | 14 | Model.getCoreHelper().setName(model, |
483 | Translator.localize("misc.untitled-profile")); | |
484 | 14 | Collection roots = new ArrayList(); |
485 | 14 | roots.add(model); |
486 | 14 | project.setRoots(roots); |
487 | 14 | project.setCurrentNamespace(model); |
488 | 14 | project.addMember(model); |
489 | // finally, apply profile configuration to the model | |
490 | 14 | applyProfileConfiguration(project, model); |
491 | 14 | } |
492 | ||
493 | /** | |
494 | * Set the save action. | |
495 | * | |
496 | * @param save the action to be used | |
497 | */ | |
498 | public void setSaveAction(Action save) { | |
499 | 900 | this.saveAction = save; |
500 | // Register with the save action with other subsystems so that | |
501 | // any changes in those subsystems will enable the | |
502 | // save button/menu item etc. | |
503 | 900 | Designer.setSaveAction(save); |
504 | 900 | } |
505 | ||
506 | /** | |
507 | * @return true is the save action is currently enabled | |
508 | * <p> | |
509 | * @deprecated for 0.27.2 by tfmorris. Use {@link Project#isDirty()}. | |
510 | */ | |
511 | public boolean isSaveActionEnabled() { | |
512 | 0 | return this.saveAction.isEnabled(); |
513 | } | |
514 | ||
515 | /** | |
516 | * Notify the gui that the | |
517 | * current project's save state has changed. There are 2 receivers: | |
518 | * the SaveProject tool icon and the title bar (for showing a *). | |
519 | * <p> | |
520 | * @deprecated for 0.27.2 by tfmorris. Use | |
521 | * {@link Project#setDirty(boolean)}. | |
522 | */ | |
523 | public void setSaveEnabled(boolean newValue) { | |
524 | 4412 | if (saveAction != null) { |
525 | 4412 | saveAction.setEnabled(newValue); |
526 | } | |
527 | 4412 | } |
528 | ||
529 | private void addProject(Project newProject) { | |
530 | 1868 | openProjects.addLast(newProject); |
531 | 1868 | } |
532 | ||
533 | /** | |
534 | * Remove the project. | |
535 | * | |
536 | * @param oldProject The project to be removed. | |
537 | */ | |
538 | public void removeProject(Project oldProject) { | |
539 | 0 | openProjects.remove(oldProject); |
540 | ||
541 | // TODO: This code can be removed when getCurrentProject is removed | |
542 | 0 | if (currentProject == oldProject) { |
543 | 0 | if (openProjects.size() > 0) { |
544 | 0 | currentProject = openProjects.getLast(); |
545 | } else { | |
546 | 0 | currentProject = null; |
547 | } | |
548 | } | |
549 | 0 | oldProject.remove(); |
550 | 0 | } |
551 | ||
552 | /** | |
553 | * Updates the top level ModelElements for all projects. | |
554 | */ | |
555 | public void updateRoots() { | |
556 | 0 | if (Model.getFacade().getUmlVersion().charAt(0) == '1') { |
557 | // not needed in UML 1.x | |
558 | 0 | return; |
559 | } | |
560 | 0 | for (Project p : getOpenProjects()) { |
561 | 0 | p.updateRoots(); |
562 | } | |
563 | 0 | firePropertyChanged(OPEN_PROJECTS_PROPERTY, |
564 | new Project[] {currentProject}, new Project[] {currentProject}); | |
565 | 0 | } |
566 | ||
567 | /** | |
568 | * Called when the model subsystem creates a command. | |
569 | * We must add this to the UndoManager. | |
570 | * | |
571 | * @param command the command. | |
572 | * @return result of the command, if any | |
573 | * @see org.argouml.model.ModelCommandCreationObserver#execute(ModelCommand) | |
574 | */ | |
575 | public Object execute(final ModelCommand command) { | |
576 | 1085 | setSaveEnabled(true); |
577 | 1085 | AbstractCommand wrappedCommand = new AbstractCommand() { |
578 | 1085 | private ModelCommand modelCommand = command; |
579 | public void undo() { | |
580 | 0 | modelCommand.undo(); |
581 | 0 | } |
582 | public boolean isUndoable() { | |
583 | 0 | return modelCommand.isUndoable(); |
584 | } | |
585 | public boolean isRedoable() { | |
586 | 0 | return modelCommand.isRedoable(); |
587 | } | |
588 | public Object execute() { | |
589 | 1085 | return modelCommand.execute(); |
590 | } | |
591 | public String toString() { | |
592 | 0 | return modelCommand.toString(); |
593 | } | |
594 | }; | |
595 | 1085 | Project p = getCurrentProject(); |
596 | 1085 | if (p != null) { |
597 | 185 | return getCurrentProject().getUndoManager().execute(wrappedCommand); |
598 | } else { | |
599 | 900 | return wrappedCommand.execute(); |
600 | } | |
601 | } | |
602 | } |