work in progress: solving of the bug number 3043572 - Main application changed
[indepmod/mmn.git] / IndependentModeler / src / cz / cvut / promod / gui / Modeler.java
blob754aeb9ab3130a3ed68b7c5a4187473ee0d42bf1
1 package cz.cvut.promod.gui;
3 import com.jidesoft.dialog.AbstractDialogPage;
4 import com.jidesoft.docking.DockableFrame;
5 import com.jidesoft.swing.JideButton;
6 import cz.cvut.promod.actions.LoadDialogAction;
7 import cz.cvut.promod.gui.dialogs.loadErrors.LoadErrorsDialog;
8 import cz.cvut.promod.gui.dialogs.newProject.NewProjectDialog;
9 import cz.cvut.promod.gui.dialogs.simpleTextFieldDialog.SimpleTextFieldDialog;
10 import cz.cvut.promod.gui.dialogs.simpleTextFieldDialog.SimpleTextFieldDialogExecutor;
11 import cz.cvut.promod.gui.dialogs.pluginsOverview.PluginsOverviewDialogDialog;
12 import cz.cvut.promod.gui.listeners.ButtonPopupAdapter;
13 import cz.cvut.promod.gui.listeners.DockFrameListener;
14 import cz.cvut.promod.gui.listeners.SideButtonListener;
15 import cz.cvut.promod.gui.settings.utils.BasicSettingPage;
16 import cz.cvut.promod.gui.settings.SettingPageData;
17 import cz.cvut.promod.gui.settings.SettingsDialog;
18 import cz.cvut.promod.gui.settings.utils.SettingPage;
19 import cz.cvut.promod.gui.support.utils.DockableFrameWrapper;
20 import cz.cvut.promod.gui.support.utils.NotationGuiHolder;
21 import cz.cvut.promod.plugin.extension.Extension;
22 import cz.cvut.promod.plugin.notationSpecificPlugIn.DockableFrameData;
23 import cz.cvut.promod.plugin.notationSpecificPlugIn.module.Module;
24 import cz.cvut.promod.plugin.notationSpecificPlugIn.notation.Notation;
25 import cz.cvut.promod.plugin.notationSpecificPlugIn.notation.NotationWorkspaceData;
26 import cz.cvut.promod.plugin.notationSpecificPlugIn.notation.utils.NotationWorkspaceDataDefault;
27 import cz.cvut.promod.plugin.notationSpecificPlugIn.notation.workspace.UpdatableWorkspaceComponent;
28 import cz.cvut.promod.services.ModelerSession;
29 import cz.cvut.promod.services.actionService.actionUtils.ProModAction;
30 import cz.cvut.promod.services.menuService.MenuControlService;
31 import cz.cvut.promod.services.menuService.MenuService;
32 import cz.cvut.promod.services.menuService.utils.ModelerMenuItem;
33 import cz.cvut.promod.services.menuService.utils.MenuItemPosition;
34 import cz.cvut.promod.services.pluginLoaderService.utils.NotationSpecificPlugins;
35 import cz.cvut.promod.services.pluginLoaderService.utils.PluginLoadErrors;
36 import cz.cvut.promod.resources.Resources;
37 import org.apache.log4j.Logger;
39 import javax.swing.*;
40 import javax.swing.tree.TreePath;
41 import java.awt.*;
42 import java.awt.event.*;
43 import java.beans.PropertyChangeEvent;
44 import java.beans.PropertyChangeListener;
45 import java.util.Collection;
46 import java.util.LinkedList;
47 import java.util.List;
49 /**
50 * ProMod, master thesis project
51 * User: Petr Zverina, petr.zverina@gmail.com
52 * Date: 16:09:42, 10.10.2009
55 /**
56 * Basic class of the host application.
58 public class Modeler extends ModelerView{
60 private static final Logger LOG = Logger.getLogger(Modeler.class);
62 public static final String ACTION_NEW_PROJECT_DIALOG = "modeler.action.new.project";
63 public static final String ACTION_EXIT = "modeler.action.exit";
64 public static final String ACTION_PROJECT_LOAD = "modeler.action.project.load";
65 public static final String ACTION_PROJECT_SAVE = "modeler.action.project.save";
66 public static final String ACTION_SWITH_USER = "modeler.action.switch.user";
67 public static final String ACTION_PROJECT_NAVIG_SHOW = "modeler.action.navigation";
68 public static final String ACTION_SETTINGS_SHOW = "modeler.action.settings";
69 public static final String ACTION_PLUGINS_OVERVIEW_SHOW = "modeler.action.plugins.overview";
71 public static final String LOAD_SYNC_TITLE_ERROR_LABEL =
72 ModelerSession.getCommonResourceBundle().getString("modeler.action.project.load.error.sync.title");
73 public static final String LOAD_SYNC_MESSAGE_ERROR_LABEL =
74 ModelerSession.getCommonResourceBundle().getString("modeler.action.project.load.error.sync.message");
75 public static final String USER_CHANGE_DIALOG_TITLE_LABEL =
76 ModelerSession.getCommonResourceBundle().getString("modeler.user.service");
77 public static final String USER_CHANGE_DIALOG_LABEL =
78 ModelerSession.getCommonResourceBundle().getString("modeler.user.name");
79 public static final String OK_LABEL =
80 ModelerSession.getCommonResourceBundle().getString("modeler.ok");
81 public static final String YES_LABEL =
82 ModelerSession.getCommonResourceBundle().getString("modeler.yes");
83 public static final String NO_LABEL =
84 ModelerSession.getCommonResourceBundle().getString("modeler.no");
85 public static final String CANCEL_LABEL =
86 ModelerSession.getCommonResourceBundle().getString("modeler.cancel");
87 public static final String USER_CHANGE_DIALOG_INVALID_LABEL =
88 ModelerSession.getCommonResourceBundle().getString("modeler.user.invalid.name");
89 public static final String SAVE_ALL_LABEL =
90 ModelerSession.getCommonResourceBundle().getString("modeler.exit.save.all");
91 public static final String SKIP_ALL_LABEL =
92 ModelerSession.getCommonResourceBundle().getString("modeler.exit.skip.all");
93 public static final String PROMOD_EXIT_LABEL =
94 ModelerSession.getCommonResourceBundle().getString("modeler.exit");
95 public static final String UNSAVED_CHANGE_LABEL =
96 ModelerSession.getCommonResourceBundle().getString("modeler.exit.diagram.unsaved.change");
97 public static final String SETTINGS_LABEL =
98 ModelerSession.getCommonResourceBundle().getString("modeler.settings");
99 public static final String FILE_LABEL =
100 ModelerSession.getCommonResourceBundle().getString("modeler.menu.file");
101 public static final String PROJECT_LABEL =
102 ModelerSession.getCommonResourceBundle().getString("modeler.menu.project");
103 public static final String EDIT_LABEL =
104 ModelerSession.getCommonResourceBundle().getString("modeler.menu.edit");
105 public static final String WINDOW_LABEL =
106 ModelerSession.getCommonResourceBundle().getString("modeler.menu.window");
107 public static final String PLUGINS_OVERVIEW_LABEL =
108 ModelerSession.getCommonResourceBundle().getString("modeler.plugins.overview");
110 public static final Object[] EXIT_DIALOG_OPTIONS = {
111 YES_LABEL,NO_LABEL, SAVE_ALL_LABEL, SKIP_ALL_LABEL, CANCEL_LABEL};
113 public static enum ExitDialogReturnValues {CONTINUE, STOP, CANCEL}
115 private final ModelerModel model;
118 public Modeler( ){
119 ModelerSession.setFrame(this);
121 this.model = new ModelerModel();
123 initActions();
125 initMainMenu();
127 initProjectNavigation();
129 initEventHandling();
133 * Initialize actions that belong to the 'virtual' "modeler" notation.
135 private void initActions(){
136 ModelerSession.getActionService().registerAction(
137 ModelerModel.MODELER_IDENTIFIER,
138 ACTION_PLUGINS_OVERVIEW_SHOW,
139 new ProModAction(PLUGINS_OVERVIEW_LABEL, null, KeyStroke.getKeyStroke(
140 KeyEvent.VK_O, java.awt.event.InputEvent.SHIFT_MASK | java.awt.event.InputEvent.CTRL_MASK)){
141 public void actionPerformed(ActionEvent event) {
142 new PluginsOverviewDialogDialog();
147 ModelerSession.getActionService().registerAction(
148 ModelerModel.MODELER_IDENTIFIER,
149 ACTION_PLUGINS_OVERVIEW_SHOW,
150 new ProModAction(PLUGINS_OVERVIEW_LABEL, null, KeyStroke.getKeyStroke(
151 KeyEvent.VK_O, java.awt.event.InputEvent.SHIFT_MASK | java.awt.event.InputEvent.CTRL_MASK)){
152 public void actionPerformed(ActionEvent event) {
153 new PluginsOverviewDialogDialog();
158 ModelerSession.getActionService().registerAction(
159 ModelerModel.MODELER_IDENTIFIER,
160 ACTION_SETTINGS_SHOW,
161 new ProModAction(SETTINGS_LABEL, null, KeyStroke.getKeyStroke(
162 KeyEvent.VK_S, java.awt.event.InputEvent.ALT_MASK | java.awt.event.InputEvent.CTRL_MASK)){
163 public void actionPerformed(ActionEvent event) {
164 SettingsDialog.showOptionsDialog(model.getSettingPagesModel());
169 ModelerSession.getActionService().registerAction(
170 ModelerModel.MODELER_IDENTIFIER,
171 ACTION_SWITH_USER,
172 new ProModAction(USER_CHANGE_DIALOG_LABEL, null, null){
173 public void actionPerformed(ActionEvent event) {
174 new SimpleTextFieldDialog(
175 USER_CHANGE_DIALOG_TITLE_LABEL,
176 USER_CHANGE_DIALOG_LABEL,
178 OK_LABEL,
179 CANCEL_LABEL,
180 new SimpleTextFieldDialogExecutor(){
181 public String execute(final String text) {
182 if(text != null && !text.isEmpty()){
183 ModelerSession.getUserService().setUser(text);
184 return null;
187 return USER_CHANGE_DIALOG_INVALID_LABEL;
190 ModelerSession.getFrame(),
191 true
195 ModelerSession.getActionService().registerAction(
196 ModelerModel.MODELER_IDENTIFIER,
197 ACTION_NEW_PROJECT_DIALOG,
198 new ProModAction(ModelerSession.getCommonResourceBundle().getString(
199 ACTION_NEW_PROJECT_DIALOG),
200 Resources.getIcon(Resources.MODELER + Resources.NEW_PROJECT_ICON),
201 KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK)){
202 public void actionPerformed(ActionEvent event) {
203 new NewProjectDialog();
207 ModelerSession.getActionService().registerAction(
208 ModelerModel.MODELER_IDENTIFIER,
209 ACTION_EXIT,
210 new ProModAction(ModelerSession.getCommonResourceBundle().getString(ACTION_EXIT), null, null){
211 public void actionPerformed(ActionEvent event) {
212 modelerExit();
216 ModelerSession.getActionService().registerAction(
217 ModelerModel.MODELER_IDENTIFIER,
218 ACTION_PROJECT_NAVIG_SHOW,
219 new ProModAction(ModelerSession.getCommonResourceBundle().getString(ACTION_PROJECT_NAVIG_SHOW), null, null){
220 public void actionPerformed(ActionEvent event) {
221 swapProjectNavigationVisibility();
223 // update control components selection
224 putValue(Action.SELECTED_KEY, projectNavigationDockableFrame.isAvailable());
225 projectNavigatorButton.setSelected(projectNavigationDockableFrame.isAvailable());
231 ModelerSession.getActionService().registerAction(
232 ModelerModel.MODELER_IDENTIFIER,
233 ACTION_PROJECT_SAVE,
234 new ProModAction(ModelerSession.getCommonResourceBundle().getString(ACTION_PROJECT_SAVE),
235 Resources.getIcon(Resources.MODELER + Resources.SAVE_ALL_ICON),
236 KeyStroke.getKeyStroke(
237 KeyEvent.VK_S, java.awt.event.InputEvent.CTRL_MASK)){
238 public void actionPerformed(ActionEvent event) {
239 LOG.debug("Action save invoked.");
241 final TreePath projectTreePath = ModelerSession.getProjectService().getSelectedProjectPath();
243 if(projectTreePath == null){
245 } else {
246 final boolean syncResult = ModelerSession.getProjectControlService().synchronize(
247 projectTreePath, true, true, false, false);
249 if (!syncResult){
250 JOptionPane.showMessageDialog(
251 ModelerSession.getFrame(),
252 LOAD_SYNC_MESSAGE_ERROR_LABEL,
253 LOAD_SYNC_TITLE_ERROR_LABEL,
254 JOptionPane.ERROR_MESSAGE);
260 ModelerSession.getActionService().registerAction(
261 ModelerModel.MODELER_IDENTIFIER,
262 ACTION_PROJECT_LOAD,
263 new LoadDialogAction(ModelerSession.getCommonResourceBundle().getString(
264 ACTION_PROJECT_LOAD),
265 Resources.getIcon(Resources.MODELER + Resources.OPEN_ICON),
266 KeyStroke.getKeyStroke(KeyEvent.VK_O, ActionEvent.CTRL_MASK)));
270 * Changed the project navigation visibility.
272 private void swapProjectNavigationVisibility(){
273 if( projectNavigationDockableFrame.isAvailable() ){
274 dockingManager.setFrameUnavailable(projectNavigationDockableFrame.getName());
275 } else{
276 final String currentNotation = ModelerSession.getProjectService().getSelectedProjectNotationIndentifier();
278 final NotationGuiHolder specification = model.getNotationGuiHolder(currentNotation);
280 if( specification != null ){
281 final List<DockableFrame> visibleDockableFrames = new LinkedList<DockableFrame>();
283 for( final DockableFrame dockableFrame : specification.getListOfFrames(NotationGuiHolder.Position.LEFT) ){
284 if( dockableFrame.isAvailable() ){
285 visibleDockableFrames.add((dockableFrame));
286 specification.getButton(dockableFrame.getName(), NotationGuiHolder.Position.LEFT).doClick();
290 dockingManager.setFrameAvailable(projectNavigationDockableFrame.getName());
292 for( final DockableFrame dockableFrame : visibleDockableFrames ){
293 specification.getButton(dockableFrame.getName(), NotationGuiHolder.Position.LEFT).doClick();
295 } else{
296 dockingManager.setFrameAvailable(projectNavigationDockableFrame.getName());
302 * Performs the terminating sequence.
304 private void modelerExit() {
305 LOG.info("Modeler is shutting down.");
307 if(!checkForUnsavedChanges()){
308 LOG.info("ProMod shut-down has been canceled by user");
309 return;
312 setVisible(false);
314 // finishing notations & modules
315 for(final String notationIdentifier : ModelerSession.getNotationService().getNotationsIdentifiers()){
316 final NotationSpecificPlugins notationSpecificPlugins = ModelerSession.getNotationService().getNotationSpecificPlugins(notationIdentifier);
318 notationSpecificPlugins.getNotation().finish();
320 for(final Module module : notationSpecificPlugins.getModules()){
321 module.finish();
325 // finishing extensions
326 for(Extension extension : ModelerSession.getExtensionService().getExtensions()){
327 extension.finish();
330 dispose();
331 System.exit(0);
335 * Looks for unsaved changes in projects.
337 * @return true if ProMod is supposed to be terminated, false if the ProMod termination has been canceled
339 private boolean checkForUnsavedChanges() {
340 for(final TreePath projectTreePath : ModelerSession.getProjectService().getProjectPaths()){
341 if(ExitDialogReturnValues.CANCEL.equals(
342 projectNavigationDockableFrame.checkForUnsavedChanges(projectTreePath, projectTreePath)
344 // ProMod termination has been canceled by user
345 return false;
349 return true;
353 * Performs the context switching mechanism.
355 private void updateView(){
356 String newNotationIdentifier = ModelerSession.getProjectService().getSelectedProjectNotationIndentifier();
357 final String oldNotationIdentifier = model.getSelectedNotation();
359 //if no diagram is selected, use default modeler view
360 if(newNotationIdentifier == null){
361 newNotationIdentifier = ModelerModel.MODELER_IDENTIFIER;
364 updateProjectDiagram(false); // order of over method invocation with respect to possible automatic sync. mechanisms
365 updateWorkspaceComponent(oldNotationIdentifier, false);
367 if(!newNotationIdentifier.equals(oldNotationIdentifier)){
368 updateModelerView(newNotationIdentifier);
369 ModelerSession.getActionControlService().updateActionsVisibility(newNotationIdentifier);
370 updateMainMenusVisibility(newNotationIdentifier);
371 updateDockableFramesVisibility(newNotationIdentifier, oldNotationIdentifier);
374 updateWorkspaceComponent(newNotationIdentifier, true); // order of over method invocation with respect to possible automatic sync. mechanisms
375 updateProjectDiagram(true);
377 model.setSelectedNotation(newNotationIdentifier);
381 * Updates the project diagram.
383 * @param update if true, update will be performed, otherwise over will be performed
385 private void updateProjectDiagram(final boolean update) {
386 if(ModelerSession.getProjectService().getSelectedDiagram() != null){
387 if(update){
388 ModelerSession.getProjectService().getSelectedDiagram().getDiagramModel().update();
389 } else {
390 ModelerSession.getProjectService().getSelectedDiagram().getDiagramModel().over();
396 * Updates the main menu items visibility.
398 * @param newNotationIdentifier is the identifier of active notation
400 private void updateMainMenusVisibility(final String newNotationIdentifier) {
401 final JMenuBar menuBar = getJMenuBar();
403 if(menuBar != null){
405 for(int i = 0; i < menuBar.getMenuCount(); i++){
406 final JMenuItem menuItem = menuBar.getMenu(i);
407 boolean isVisible = updateMenuItemVisibility(menuItem, newNotationIdentifier);
409 if(isVisible){
410 menuItem.setEnabled(true);
411 } else {
412 menuItem.setEnabled(false);
420 * Recursively goes through the menu structure and ensures that only items related to the currently selected notation
421 * will be enabled.
423 * @param parentMenuItem is the menu where the recursion begins
424 * @param newNotationIdentifier is the identifier of selected notation
426 * @return true if the parentMenuItem is supposed to be disabled, false otherwise
428 private boolean updateMenuItemVisibility(final JMenuItem parentMenuItem, final String newNotationIdentifier) {
429 boolean isEnabled = false;
431 parentMenuItem.setVisible(true); // always start with all items visible
433 if(parentMenuItem instanceof JMenu){
435 final JMenu menu = (JMenu) parentMenuItem;
436 for(int i = 0; i < menu.getItemCount(); i++){
437 final JMenuItem menuItem = menu.getItem(i);
439 if(menuItem != null){ //separator is returned like a null item
440 isEnabled |= updateMenuItemVisibility(menuItem, newNotationIdentifier);
444 menu.setEnabled(isEnabled);
445 return isEnabled;
448 // menu item, hide relatives (menu items with the same text)
449 final boolean menuItemEnabled = parentMenuItem.isEnabled();
451 if(parentMenuItem instanceof ModelerMenuItem && !menuItemEnabled){
452 final ModelerMenuItem menuItem = (ModelerMenuItem) parentMenuItem;
454 final List<ModelerMenuItem> relatives = menuItem.getListOfRelatives();
455 if(relatives != null){
456 if(relatives.isEmpty()){
457 parentMenuItem.setVisible(false);
458 } else {
459 if(isAnotherRelativeVisible(relatives)){
460 parentMenuItem.setVisible(false);
466 return menuItemEnabled;
470 * Checks the list of relatives (relative are items in the menu under the same root with the same text on it) and
471 * decides whether this any of relative items is visible or not.
473 * @param relatives is the list of relative items
474 * @return true if any another relative item is visible, false otherwise
476 private boolean isAnotherRelativeVisible(final List<ModelerMenuItem> relatives) {
477 if(relatives == null || relatives.isEmpty()){
478 return false;
481 for(ModelerMenuItem modelerMenuItem : relatives){
482 if(modelerMenuItem instanceof JMenuItem){
483 final JMenuItem menuItem = (JMenuItem) modelerMenuItem;
484 if(menuItem.isEnabled()){
485 return true;
490 return false;
494 * Performs the context switch.
496 * @param newNotationIdentifier is the identifier of active notation.
498 private void updateModelerView(final String newNotationIdentifier) {
499 if(newNotationIdentifier != null){
500 cardLayoutLeftSidePane.show(leftSidePane, newNotationIdentifier);
501 cardLayoutRightSidePane.show(rightSidePane, newNotationIdentifier);
502 cardLayoutBottomSidePane.show(bottomSidePane, newNotationIdentifier);
503 cardLayoutTopSidePane.show(topSidePane, newNotationIdentifier);
505 cardLayoutWorkspacePane.show(workspacePane, newNotationIdentifier);
507 cardLayoutToolBar.show(toolBarPane, newNotationIdentifier);
509 cardLayoutStatusBar.show(statusBarPane, newNotationIdentifier);
511 } else {
512 LOG.error("Modeler view update error. Notation name cannot be null.");
517 * Performs the update() or ever() methods on workspace component if this component implements the
518 * UpdatableWorkspaceComponent interface.
520 * @param notationIdentifier is the identifier of the notation to which the workspace component belongs
521 * @param update is true when update() method is supposed to be invoked, the over() methods is invoked otherwise
523 private void updateWorkspaceComponent(final String notationIdentifier, final boolean update) {
524 if(notationIdentifier != null && !ModelerModel.MODELER_IDENTIFIER.equals(notationIdentifier)){
525 final JComponent workspaceComponent;
526 try{
527 workspaceComponent = model.getNotationGuiHolder(notationIdentifier).getNotationWorkspace().getWorkspaceComponentSingleton();
529 if(workspaceComponent instanceof UpdatableWorkspaceComponent){
530 final UpdatableWorkspaceComponent updatableWorkspaceComponent = (UpdatableWorkspaceComponent)workspaceComponent;
532 if(update){
533 updatableWorkspaceComponent.update();
534 } else {
535 ModelerSession.clearFrameTitleText();
536 updatableWorkspaceComponent.over();
540 } catch (NullPointerException exception){
541 LOG.error("Not workspace provided, notationIdentifier: " + notationIdentifier);
547 * Updates the dockable frame visibility.
549 * @param newNotationIdentifier is the identifier of active notation
550 * @param oldNotationIdentifier is the identifier of previous notation.
552 private void updateDockableFramesVisibility(final String newNotationIdentifier, final String oldNotationIdentifier) {
553 if(newNotationIdentifier == null || newNotationIdentifier.equals(oldNotationIdentifier)){
554 // should never happened
555 LOG.debug("UpdateDockableFramesVisibility method has been invoked, even though newNotationIdentifier is the same as oldNotationIdentifier.");
558 if(!ModelerModel.MODELER_IDENTIFIER.equals(oldNotationIdentifier) && oldNotationIdentifier != null){
559 model.getNotationGuiHolder(oldNotationIdentifier).unable();
562 if(!ModelerModel.MODELER_IDENTIFIER.equals(newNotationIdentifier)){
563 model.getNotationGuiHolder(newNotationIdentifier).enable();
568 * Initialize main menu.
570 private void initMainMenu() {
571 final MenuControlService mainMenuControlService;
572 try{
573 mainMenuControlService = (MenuControlService) ModelerSession.getMenuService();
574 } catch(ClassCastException exception){
575 LOG.error("Main menu initialization not possible.", exception);
576 return;
579 setJMenuBar(mainMenuControlService.getMenuBar());
581 // insert common menu items
582 // 'file' menu
583 ModelerSession.getMenuService().insertMainMenuItem(ModelerSession.getActionService().getAction(
584 ModelerModel.MODELER_IDENTIFIER, ACTION_EXIT),
585 new MenuItemPosition(FILE_LABEL), MenuService.MenuSeparator.BEFORE
588 // 'project' menu
589 ModelerSession.getMenuService().insertMainMenuItem(ModelerSession.getActionService().getAction(
590 ModelerModel.MODELER_IDENTIFIER, ACTION_NEW_PROJECT_DIALOG),
591 new MenuItemPosition(PROJECT_LABEL, MenuItemPosition.PlacementStyle.FIRST)
594 ModelerSession.getMenuService().insertMainMenuItem(ModelerSession.getActionService().getAction(
595 ModelerModel.MODELER_IDENTIFIER, ACTION_PROJECT_SAVE),
596 new MenuItemPosition(PROJECT_LABEL), MenuService.MenuSeparator.BEFORE
598 ModelerSession.getMenuService().insertMainMenuItem(ModelerSession.getActionService().getAction(
599 ModelerModel.MODELER_IDENTIFIER, ACTION_PROJECT_LOAD),
600 new MenuItemPosition(PROJECT_LABEL)
603 // 'edit' Menu
604 ModelerSession.getMenuService().insertMainMenuItem(ModelerSession.getActionService().getAction(
605 ModelerModel.MODELER_IDENTIFIER, ACTION_SETTINGS_SHOW),
606 new MenuItemPosition(EDIT_LABEL)
609 // 'window' menu
610 ModelerSession.getMenuService().insertMainMenuItem(ModelerSession.getActionService().getAction(
611 ModelerModel.MODELER_IDENTIFIER, ACTION_PROJECT_NAVIG_SHOW),
612 new MenuItemPosition(WINDOW_LABEL), true
614 ModelerSession.getMenuService().insertMainMenuItem(ModelerSession.getActionService().getAction(
615 ModelerModel.MODELER_IDENTIFIER, ACTION_PLUGINS_OVERVIEW_SHOW),
616 new MenuItemPosition(WINDOW_LABEL)
621 * Initialize the event handling.
623 private void initEventHandling(){
624 ModelerSession.getUserService().getUserValueModel().addValueChangeListener(
625 new PropertyChangeListener(){
626 public void propertyChange(PropertyChangeEvent evt) {
627 loggedUserLabel.setText(ModelerSession.getUserService().getUser());
632 switchUserButton.addActionListener(new ActionListener(){
633 public void actionPerformed(ActionEvent e) {
634 ModelerSession.getActionService().getAction(ModelerModel.MODELER_IDENTIFIER, ACTION_SWITH_USER).actionPerformed(null);
638 ModelerSession.getProjectService().getSelectedItem().addValueChangeListener(new PropertyChangeListener(){
639 public void propertyChange(PropertyChangeEvent evt) {
640 updateView();
644 // listener of window's closing button (cross button)
645 this.addWindowListener(new WindowAdapter(){
646 @Override
647 public void windowClosing(WindowEvent e){
649 ModelerSession.getActionService().getAction(ModelerModel.MODELER_IDENTIFIER, ACTION_EXIT).actionPerformed(null);
653 projectNavigatorButton.addActionListener(ModelerSession.getActionService().getAction(ModelerModel.MODELER_IDENTIFIER, ACTION_PROJECT_NAVIG_SHOW));
657 * Installs the plugins into the gui.
659 public void deployNotationSpecificPlugIns( ){
660 for(final String notationIdentifier : ModelerSession.getNotationService().getNotationsIdentifiers()){
661 final NotationSpecificPlugins notationSpecificPlugins = ModelerSession.getNotationService().getNotationSpecificPlugins(notationIdentifier);
663 installNotationsAndModules(notationSpecificPlugins);
668 * Shows the application frame window.
670 public void showFrame(){
671 // update view to initial state
672 updateView();
674 dockingManager.loadLayoutData();
676 dockingManager.setFrameUnavailable(projectNavigationDockableFrame.getName());
678 for( final NotationGuiHolder notationGuiHolder : model.getNotationGuiHolders() ){
679 for( final DockableFrameWrapper wrapper : notationGuiHolder.getAllDockableFrameFacades() ){
680 dockingManager.setFrameAvailable(wrapper.getDockableFrame().getName());
681 dockingManager.setFrameUnavailable(wrapper.getDockableFrame().getName());
685 setVisible(true);
687 projectNavigatorButton.doClick();
689 showLoadingErrors();
693 * Decides whether there were any errors during plugins loading and if there were any, then show a visual report
694 * about these errors.
696 private void showLoadingErrors(){
697 final List<PluginLoadErrors> errors = ModelerSession.getNotationService().getErrors();
699 if(errors == null){
700 LOG.error("Nullary loading error info.");
701 return;
704 if(!errors.isEmpty()){
705 new LoadErrorsDialog(errors);
710 * Installs the notations ad modules.
712 * @param notationSpecificPlugins is the holder of notations and it's modules
714 private void installNotationsAndModules(final NotationSpecificPlugins notationSpecificPlugins ){
715 final NotationGuiHolder notationGuiHolder = new NotationGuiHolder(
716 notationSpecificPlugins.getNotation().getIdentifier(),
717 dockingManager
720 model.addNotationGuiHolder(notationGuiHolder);
722 final Collection<DockableFrameData> dockableFramesData = notationSpecificPlugins.getDockableFramesData();
724 if( dockableFramesData != null ){
725 for( final DockableFrameData item : dockableFramesData ){
727 final DockableFrame frame = createDockableFrame(
728 item.getDockableFrameComponent(),
729 item.getInitialPosition(),
730 item.getDockableFrameTitle(),
731 item.isMaximizable(),
732 item.getInitialState());
734 final JMenu menu = ModelerSession.getComponentFactoryService().createMenu(
735 ModelerSession.getCommonResourceBundle().getString("modeler.dockable.frame.move"));
737 final JMenuItem moveToLeftMenuItem = ModelerSession.getComponentFactoryService().createMenuItem(
738 ModelerSession.getCommonResourceBundle().getString("modeler.dockable.frame.move.left"));
739 moveToLeftMenuItem.addActionListener(new MenuItemMoveListener(notationGuiHolder, frame, NotationGuiHolder.Position.LEFT));
741 final JMenuItem moveToRightMenuItem = ModelerSession.getComponentFactoryService().createMenuItem(
742 ModelerSession.getCommonResourceBundle().getString("modeler.dockable.frame.move.right"));
743 moveToRightMenuItem.addActionListener(new MenuItemMoveListener(notationGuiHolder, frame, NotationGuiHolder.Position.RIGHT));
745 final JMenuItem moveToTopMenuItem = ModelerSession.getComponentFactoryService().createMenuItem(
746 ModelerSession.getCommonResourceBundle().getString("modeler.dockable.frame.move.top"));
747 moveToTopMenuItem.addActionListener(new MenuItemMoveListener(notationGuiHolder, frame, NotationGuiHolder.Position.TOP));
749 final JMenuItem moveToBottomMenuItem = ModelerSession.getComponentFactoryService().createMenuItem(
750 ModelerSession.getCommonResourceBundle().getString("modeler.dockable.frame.move.bottom"));
751 moveToBottomMenuItem.addActionListener(new MenuItemMoveListener(notationGuiHolder, frame, NotationGuiHolder.Position.BOTTOM));
753 final JPopupMenu popupMenu = ModelerSession.getComponentFactoryService().createPopupMenu();
755 if(item.getAllowedDockableFramePositions() != null){
756 boolean insertMenu = false;
758 for(final NotationGuiHolder.Position position : NotationGuiHolder.Position.values()){
759 if(item.getAllowedDockableFramePositions().contains(position)){
760 switch (position){
761 case LEFT:
762 menu.add(moveToLeftMenuItem);
763 insertMenu = true;
764 break;
765 case RIGHT:
766 menu.add(moveToRightMenuItem);
767 insertMenu = true;
768 break;
769 case TOP:
770 menu.add(moveToTopMenuItem);
771 insertMenu = true;
772 break;
773 case BOTTOM:
774 menu.add(moveToBottomMenuItem);
775 insertMenu = true;
776 break;
777 default:
778 LOG.error("No such a choice for allowed position of dockable frame.");
783 if(insertMenu){
784 popupMenu.add(menu);
788 final JideButton button;
789 switch (item.getInitialPosition()){
790 case BOTTOM:
791 case TOP:
792 button = ModelerSession.getComponentFactoryService().createJideButton(item.getDockableFrameTitle(),
793 item.getButtonIcon(),
795 break;
796 default:
797 // case LEFT:
798 // case RIGHT:
799 button = ModelerSession.getComponentFactoryService().createJideButton(item.getDockableFrameTitle(),
800 item.getButtonIcon(),
804 button.addActionListener(new SideButtonListener(notationGuiHolder, dockingManager, frame));
805 button.addMouseListener(new ButtonPopupAdapter(button, popupMenu));
807 frame.addDockableFrameListener(new DockFrameListener(notationGuiHolder, dockingManager));
809 notationGuiHolder.addFrameWithButton(
810 frame,
811 button,
812 popupMenu,
813 moveToLeftMenuItem,
814 moveToRightMenuItem,
815 moveToBottomMenuItem,
816 moveToTopMenuItem,
817 item.getInitialPosition(),
818 item.getInitialState());
822 final String notationIdentifier = notationSpecificPlugins.getNotation().getIdentifier();
824 // insert notation workspace
825 if( notationSpecificPlugins.getNotation().getNotationWorkspaceData() != null ){
826 notationGuiHolder.setNotationWorkspace(notationSpecificPlugins.getNotation().getNotationWorkspaceData());
827 } else {
828 notationGuiHolder.setNotationWorkspace(new NotationWorkspaceDataDefault(notationIdentifier));
830 LOG.error("No workspace definition provided. Default panel has been inserted instead. " +
831 "Notation identifier: " + notationIdentifier);
834 // insert notation specific tool bar
835 addToolBarPane(notationIdentifier, ModelerSession.getToolBarControlService().getCommandBar(notationIdentifier));
837 // insert notation specific status bar
838 addStatusBar(notationIdentifier, ModelerSession.getStatusBarControlService().getStatusBar(notationIdentifier));
840 deployWorkspace(notationIdentifier);
841 deployButtons(notationIdentifier);
845 * Installs the workspace component.
847 * @param notationIdentifier is the identifier of associated notation
849 private void deployWorkspace( final String notationIdentifier ){
850 final NotationWorkspaceData notationWorkspaceData = model.getNotationGuiHolder(notationIdentifier).getNotationWorkspace();
852 final JComponent workspaceComponent = notationWorkspaceData.getWorkspaceComponentSingleton();
854 if(!(workspaceComponent instanceof UpdatableWorkspaceComponent)){
855 LOG.warn("The obtained workspace component for notation (" + notationIdentifier + ") doesn't implement the UpdatableWorkspaceComponent inytercae. " +
856 "Any methods of this interface won't be never invoked for this workspace component.");
859 addMainWindowPane(notationIdentifier, workspaceComponent);
863 * Deploys buttons.
865 * @param notationIdentifier is the notation identifier.
867 private void deployButtons( final String notationIdentifier ){
868 final NotationGuiHolder spec = model.getNotationGuiHolder(notationIdentifier);
870 addSidePane(notationIdentifier, rightSidePane, spec.getListOfButtons(
871 NotationGuiHolder.Position.RIGHT), true);
873 addSidePane(notationIdentifier, leftSidePane, spec.getListOfButtons(
874 NotationGuiHolder.Position.LEFT), true);
876 addSidePane(notationIdentifier, bottomSidePane, spec.getListOfButtons(
877 NotationGuiHolder.Position.BOTTOM), false);
879 addSidePane(notationIdentifier, topSidePane, spec.getListOfButtons(
880 NotationGuiHolder.Position.TOP), false);
884 * Initializes the common settings dialog.
886 public void initSettingsDialog() {
887 LOG.info("Initializing settings dialog.");
889 for(final Notation notation : ModelerSession.getNotationService().getNotations()){
890 final NotationSpecificPlugins notationSpecificPlugins =
891 ModelerSession.getNotationService().getNotationSpecificPlugins(notation.getIdentifier());
893 // init notation's settings screens
894 SettingPageData settingInfo = notationSpecificPlugins.getNotation().getSettingPages();
895 List<AbstractDialogPage> pages = new LinkedList<AbstractDialogPage>();
896 this.createPages(pages, settingInfo);
898 if(pages.size() == 0){
899 LOG.info("Notation " + notation.getIdentifier() + " provides nullary setting pages list.");
902 pages.add(0, new BasicSettingPage(notation.getFullName()));
904 final AbstractDialogPage parentPage = pages.get(0);
906 installPagesParent(pages, parentPage);
908 model.addSettingPages(pages);
910 // init module's settings screens
911 for(final Module module : notationSpecificPlugins.getModules()){
912 settingInfo = module.getSettingPages();
913 pages.clear();
914 this.createPages(pages, settingInfo);
916 if(pages != null){
917 installPagesParent(pages, parentPage);
919 model.addSettingPages(pages);
921 } else {
922 LOG.info("Module " + module.getIdentifier() + " provides nullary setting pages list.");
927 // init extension's settings screens
928 for(final Extension extension : ModelerSession.getExtensionService().getExtensions()){
929 SettingPageData settingInfo = extension.getSettingPages();
930 List<AbstractDialogPage> pages = new LinkedList<AbstractDialogPage>();
931 this.createPages(pages, settingInfo);
933 if(pages == null){
934 LOG.info("Extension " + extension.getIdentifier() + " provides nullary setting pages list.");
935 pages = new LinkedList<AbstractDialogPage>();
939 pages.add(0, new BasicSettingPage(extension.getName()));
941 final AbstractDialogPage parentPage = pages.get(0);
943 installPagesParent(pages, parentPage);
945 model.addSettingPages(pages);
949 private void createPages(List<AbstractDialogPage> pageList, SettingPageData settingInfo) {
950 SettingPage page = new SettingPage(settingInfo);
951 List<SettingPageData> children = settingInfo.getChildren();
952 for (SettingPageData child : children) {
953 this.createPages(pageList, child);
959 * Sets the proper parent to all settings pages. If the parent of the page is already set then nothing is changed.
961 * @param pages is the page
962 * @param parentDialogPage is the parent of the page
964 private void installPagesParent(final List<AbstractDialogPage> pages, final AbstractDialogPage parentDialogPage) {
965 if(pages.size() > 1){
966 pages.get(1).setParentPage(parentDialogPage);
969 for(final AbstractDialogPage page : pages){
970 if(page.getParent() == null && page != parentDialogPage){
971 page.setParentPage(parentDialogPage);
977 * Performs dockable frame moves.
979 private class MenuItemMoveListener implements ActionListener{
981 private final NotationGuiHolder notationGuiHolder;
982 private final DockableFrame dockableFrame;
983 private final NotationGuiHolder.Position directionOfMovement;
985 public MenuItemMoveListener( final NotationGuiHolder notationGuiHolder,
986 final DockableFrame correspondingFrame,
987 final NotationGuiHolder.Position directionOfMovement){
988 this.notationGuiHolder = notationGuiHolder;
989 this.dockableFrame = correspondingFrame;
990 this.directionOfMovement = directionOfMovement;
993 public void actionPerformed( ActionEvent e ){
994 try{
995 final String notationIdentifier = notationGuiHolder.getNotationIdentifier();
996 final String dockableFrameName = dockableFrame.getName();
998 NotationGuiHolder.Position oldPosition = notationGuiHolder.getPosition(dockableFrameName);
1000 notationGuiHolder.moveButtonAndFrame(dockableFrameName, directionOfMovement);
1002 final JPanel oldPanel;
1003 final CardLayout oldCardLayout;
1004 boolean isVertical;
1005 switch (oldPosition){
1006 case LEFT:
1007 oldPanel = leftSidePane;
1008 oldCardLayout = cardLayoutLeftSidePane;
1009 isVertical = true;
1010 break;
1011 case RIGHT:
1012 oldPanel = rightSidePane;
1013 oldCardLayout = cardLayoutRightSidePane;
1014 isVertical = true;
1015 break;
1016 case TOP:
1017 oldPanel = topSidePane;
1018 oldCardLayout = cardLayoutTopSidePane;
1019 isVertical = false;
1020 break;
1021 case BOTTOM:
1022 oldPanel = bottomSidePane;
1023 oldCardLayout = cardLayoutBottomSidePane;
1024 isVertical = false;
1025 break;
1026 default:
1027 oldPanel = null;
1028 isVertical = true;
1029 oldCardLayout = null;
1030 LOG.error("No such a position for dockable frame.");
1033 addSidePane(notationIdentifier, oldPanel, notationGuiHolder.getListOfButtons(oldPosition), isVertical);
1034 oldCardLayout.show(oldPanel, notationIdentifier);
1037 final JPanel newPanel;
1038 final NotationGuiHolder.Position newPosition;
1039 final CardLayout newCardLayout;
1040 switch(directionOfMovement){
1041 case LEFT:
1042 newPanel = leftSidePane;
1043 newPosition = NotationGuiHolder.Position.LEFT;
1044 isVertical = true;
1045 newCardLayout = cardLayoutLeftSidePane;
1046 break;
1047 case RIGHT:
1048 newPanel = rightSidePane;
1049 newPosition = NotationGuiHolder.Position.RIGHT;
1050 isVertical = true;
1051 newCardLayout = cardLayoutRightSidePane;
1052 break;
1053 case BOTTOM:
1054 newPanel = bottomSidePane;
1055 newPosition = NotationGuiHolder.Position.BOTTOM;
1056 isVertical = false;
1057 newCardLayout = cardLayoutBottomSidePane;
1058 break;
1059 case TOP:
1060 newPanel = topSidePane;
1061 newPosition = NotationGuiHolder.Position.TOP;
1062 isVertical = false;
1063 newCardLayout = cardLayoutTopSidePane;
1064 break;
1065 default:
1066 newPanel = null;
1067 newPosition = null;
1068 isVertical = true;
1069 newCardLayout = null;
1070 LOG.error("No such a position for dockable frame.");
1073 addSidePane(notationIdentifier, newPanel, notationGuiHolder.getListOfButtons(newPosition), isVertical);
1074 newCardLayout.show(newPanel, notationIdentifier);
1076 } catch(IllegalArgumentException exception){
1077 LOG.error("Illegal position or unknown frame during low level navigation movement.", exception);