/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.smart.cmd; import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.HashMap; import java.util.Iterator; import javax.swing.Action; import javax.swing.JOptionPane; import javax.swing.undo.UndoManager; import javax.swing.undo.UndoableEdit; import com.servoy.j2db.ControllerUndoManager; import com.servoy.j2db.FormController; import com.servoy.j2db.FormManager; import com.servoy.j2db.IForm; import com.servoy.j2db.IModeManager; import com.servoy.j2db.ISmartClientApplication; import com.servoy.j2db.cmd.ICmd; import com.servoy.j2db.cmd.ICmdManagerInternal; import com.servoy.j2db.cmd.IHandleUndoRedo; import com.servoy.j2db.persistence.IRepository; import com.servoy.j2db.persistence.Solution; import com.servoy.j2db.smart.SwingFormManager; import com.servoy.j2db.util.Debug; /** * The manager handling cmds, executing them and enables disables! * * @author jblok */ public class CmdManager implements ICmdManagerInternal, PropertyChangeListener, IHandleUndoRedo { private UndoManager undoManager; private ControllerUndoManager controllerUndoManager; private final UndoAction undoAction; private final RedoAction redoAction; protected HashMap<String, Action> actions = new HashMap<String, Action>(); protected ISmartClientApplication application; /** * Constructor I */ public CmdManager(ISmartClientApplication app) { application = app; // undoManager = new UndoManager(); // undoManager.setLimit(50); redoAction = new RedoAction(app, this); undoAction = new UndoAction(app, this); actions.put("cmdredo", redoAction); //$NON-NLS-1$ actions.put("cmdundo", undoAction); //$NON-NLS-1$ //this is now handled in Displays adapter, due to jdk 131 // propListener = new PropertyListener(); // FocusManager focus = DefaultFocusManager.getCurrentManager(); // focus.addPropertyChangeListener("focusOwner",propListener); } public void setCurrentUndoManager(UndoManager man) { undoManager = man; // set to null so that it doesn't hold the state if it was a tabpanel if (man instanceof ControllerUndoManager) { ((ControllerUndoManager)undoManager).setFormUndoManager(null); } if (controllerUndoManager != null) { controllerUndoManager.setFormUndoManager(man); } } public void setControllerUndoManager(ControllerUndoManager controllerUndo) { if (this.controllerUndoManager != controllerUndo) { if (this.controllerUndoManager != null) this.controllerUndoManager.setFormUndoManager(null); this.controllerUndoManager = controllerUndo; if (this.controllerUndoManager != null) this.controllerUndoManager.setFormUndoManager(undoManager); } } /** * Register a named Action */ public void registerAction(String name, Action a) { actions.put(name.toLowerCase(), a); } /** * get a previous registered action */ public Action getRegisteredAction(String name) { return actions.get(name.toLowerCase()); } public void propertyChange(PropertyChangeEvent evt) { String name = evt.getPropertyName(); if ("repository".equals(name)) //$NON-NLS-1$ { final IRepository repository = (IRepository)evt.getNewValue(); Action cmdnewsolution = actions.get("cmdnewsolution"); //$NON-NLS-1$ if (cmdnewsolution != null) cmdnewsolution.setEnabled(repository != null); if (autoOpenSolutionSelectDialog) { final Action cmdopensolution = actions.get("cmdopensolution"); //$NON-NLS-1$ if (cmdopensolution != null) { application.invokeLater(new Runnable() { public void run() { cmdopensolution.setEnabled(repository != null); if (repository != null) { try { if (repository.getRootObjectMetaDatasForType(IRepository.SOLUTIONS).length != 0 && application.getSolution() == null && (application.getFlattenedSolution() == null || !application.getFlattenedSolution().isLoadingSolution())) { executeCmd((ICmd)cmdopensolution, null); } } catch (Exception ex) { Debug.error(ex); } } } }); } } } else if ("solution".equals(name)) //$NON-NLS-1$ { Solution solution = (Solution)evt.getNewValue(); ableFormRelatedBrowseActions(solution != null); ableFormRelatedDataEditActions(solution != null); undoAction.setEnabled(solution != null); redoAction.setEnabled(solution != null); Action cmdclose = actions.get("cmdclose"); //$NON-NLS-1$ if (cmdclose != null) cmdclose.setEnabled(solution != null); Action cmdsolutionsettings = actions.get("cmdsolutionsettings"); //$NON-NLS-1$ if (cmdsolutionsettings != null) cmdsolutionsettings.setEnabled(solution != null); // Action cmdprint = (Action) actions.get("cmdprint"); // if (cmdprint != null) cmdprint.setEnabled(enable); //TODO:could be optimized by using fast method getFormCount if (solution != null && application.getFlattenedSolution().getForms(false).hasNext()) { ableFormRelatedActions(true); } else { ableFormRelatedActions(false); } } else if ("mode".equals(name)) //$NON-NLS-1$ { int oldmode = ((Integer)evt.getOldValue()).intValue(); Action menuselectaction = actions.get("menuselectaction"); //$NON-NLS-1$ int mode = ((Integer)evt.getNewValue()).intValue(); switch (mode) { case IModeManager.FIND_MODE : break; case IModeManager.PREVIEW_MODE : break; case IModeManager.EDIT_MODE : default : if (menuselectaction != null) menuselectaction.setEnabled(true); } ableFormRelatedFindActions(mode == IModeManager.FIND_MODE); Action cmdfindmode = actions.get("cmdfindmode"); //$NON-NLS-1$ if (cmdfindmode != null) cmdfindmode.setEnabled(mode == IModeManager.EDIT_MODE); if (mode == IModeManager.FIND_MODE) { ableFormRelatedBrowseActions(false); ableFormRelatedDataEditActions(true); } else { ableFormRelatedBrowseActions(mode == IModeManager.EDIT_MODE); } } else if ("formCreated".equals(name)) //$NON-NLS-1$ { ableFormRelatedActions(evt.getNewValue() != null); } else if ("undomanager".equals(name)) //$NON-NLS-1$ { String sUndoRedo = (String)evt.getOldValue(); Boolean bValue = (Boolean)evt.getNewValue(); Action menuUndoRedo = actions.get(sUndoRedo); if (menuUndoRedo != null) menuUndoRedo.setEnabled(bValue.booleanValue()); } } protected void ableFormRelatedActions(boolean enable) { // Action menuwindowaction = (Action) actions.get("menuwindowaction"); // if (menuwindowaction != null) menuwindowaction.setEnabled(enable); Action menumethodsaction = actions.get("menumethodsaction"); //$NON-NLS-1$ if (menumethodsaction != null) menumethodsaction.setEnabled(enable); Action menuviewaction = actions.get("menuviewaction"); //$NON-NLS-1$ if (menuviewaction != null) menuviewaction.setEnabled(enable); Action menuselectaction = actions.get("menuselectaction"); //$NON-NLS-1$ if (menuselectaction != null) menuselectaction.setEnabled(enable); //enable modes Action cmdbrowsemode = actions.get("cmdbrowsemode"); //$NON-NLS-1$ if (cmdbrowsemode != null) cmdbrowsemode.setEnabled(enable); Action cmdpreviewmode = actions.get("cmdpreviewmode"); //$NON-NLS-1$ if (cmdpreviewmode != null) cmdpreviewmode.setEnabled(enable); Action cmdfindmode = actions.get("cmdfindmode"); //$NON-NLS-1$ if (cmdfindmode != null) cmdfindmode.setEnabled(enable); Action action = actions.get("cmdpaste"); //$NON-NLS-1$ if (action != null) action.setEnabled(enable); action = actions.get("cmdcopy"); //$NON-NLS-1$ if (action != null) action.setEnabled(enable); action = actions.get("cmdcut"); //$NON-NLS-1$ if (action != null) action.setEnabled(enable); action = actions.get("cmdselectall"); //$NON-NLS-1$ if (action != null) action.setEnabled(enable); action = actions.get("cmdshowscriptdebugger"); //$NON-NLS-1$ if (action != null) action.setEnabled(enable); action = actions.get("cmdshowi18n"); //$NON-NLS-1$ if (action != null) action.setEnabled(enable); action = actions.get("cmdshowmethods"); //$NON-NLS-1$ if (action != null) action.setEnabled(enable); } protected void ableFormRelatedDataEditActions(boolean enable) { Action cmdfindall = actions.get("cmdfindall"); //$NON-NLS-1$ if (cmdfindall != null) cmdfindall.setEnabled(enable); Action cmdsavedata = actions.get("cmdsavedata"); //$NON-NLS-1$ if (cmdsavedata != null) cmdsavedata.setEnabled(enable); Action cmdrecopyvalues = actions.get("cmdrecopyvalues"); //$NON-NLS-1$ if (cmdrecopyvalues != null) cmdrecopyvalues.setEnabled(enable); Action cmddeleterecord = actions.get("cmddeleterecord"); //$NON-NLS-1$ if (cmddeleterecord != null) cmddeleterecord.setEnabled(enable); Action cmdnewrecord = actions.get("cmdnewrecord"); //$NON-NLS-1$ if (cmdnewrecord != null) cmdnewrecord.setEnabled(enable); Action cmdduplicaterecord = actions.get("cmdduplicaterecord"); //$NON-NLS-1$ if (cmdduplicaterecord != null) cmdduplicaterecord.setEnabled(enable); Action cmdnextrecord = actions.get("cmdnextrecord"); //$NON-NLS-1$ if (cmdnextrecord != null) cmdnextrecord.setEnabled(enable); Action cmdprevrecord = actions.get("cmdprevrecord"); //$NON-NLS-1$ if (cmdprevrecord != null) cmdprevrecord.setEnabled(enable); } public void ableFormRelatedFindActions(boolean enable) { FormManager fm = (FormManager)application.getFormManager(); IForm[] visibleRootFormsInFind = (fm != null) ? fm.getVisibleRootFormsInFind() : null; boolean thereAreUsableVisibleFormsInFind = ((visibleRootFormsInFind != null) && (visibleRootFormsInFind.length > 0)); // if there are visible forms that are still in find mode, even though enabled = false (for example // when another form exits find mode - see unrelated tab panels) the actions must still remain enabled (although it is a strange case) boolean shouldPerform = false; if (thereAreUsableVisibleFormsInFind) { for (IForm f : visibleRootFormsInFind) { if (!(f instanceof FormController) || ((FormController)f).getForm() == null || ((FormController)f).getForm().getOnSearchCmdMethodID() >= 0) { shouldPerform = true; break; } } } else { shouldPerform = true; } // if we want to enable find actions we check for onsearchcmd of the form; if set to none, actions are not enabled if (shouldPerform) { Action cmdperformfind = actions.get("cmdperformfind"); //$NON-NLS-1$ if (cmdperformfind != null) cmdperformfind.setEnabled(enable || thereAreUsableVisibleFormsInFind); Action cmdreducefind = actions.get("cmdreducefind"); //$NON-NLS-1$ if (cmdreducefind != null) cmdreducefind.setEnabled(enable || thereAreUsableVisibleFormsInFind); Action cmdextendfind = actions.get("cmdextendfind"); //$NON-NLS-1$ if (cmdextendfind != null) cmdextendfind.setEnabled(enable || thereAreUsableVisibleFormsInFind); } // this action must be enabled even if onsearchcmd is set to none... Action cmdstopsearchfindall = actions.get("cmdstopsearchfindall"); //$NON-NLS-1$ if (cmdstopsearchfindall != null) cmdstopsearchfindall.setEnabled(enable); } protected void ableFormRelatedBrowseActions(boolean enable) { FormManager fm = (FormManager)application.getFormManager(); int view = FormController.LOCKED_LIST_VIEW; if (enable) { IForm formPanel = fm.getCurrentForm(); if (formPanel != null) { view = formPanel.getView(); } } Action cmdviewasform = actions.get("cmdviewasform"); //$NON-NLS-1$ if (cmdviewasform != null) cmdviewasform.setEnabled(view < 3); Action cmdviewaslist = actions.get("cmdviewaslist"); //$NON-NLS-1$ if (cmdviewaslist != null) cmdviewaslist.setEnabled(view < 3); // Action cmdviewastable = (Action) actions.get("cmdviewastable"); //$NON-NLS-1$ // if (cmdviewastable != null) cmdviewastable.setEnabled(enable);//TODO:enable when implemented // Action cmdduplicaterecord = (Action) actions.get("cmdduplicaterecord"); //$NON-NLS-1$ // if (cmdduplicaterecord != null) cmdduplicaterecord.setEnabled(enable); // Action cmdomitrecord = (Action) actions.get("cmdomitrecord"); //$NON-NLS-1$ // if (cmdomitrecord != null) cmdomitrecord.setEnabled(enable); // Action cmdrevertrecords = (Action) actions.get("cmdrevertrecords"); //$NON-NLS-1$ // if (cmdrevertrecords != null) cmdrevertrecords.setEnabled(enable); // Action cmdshowomitrecords = (Action) actions.get("cmdshowomitrecords"); //$NON-NLS-1$ // if (cmdshowomitrecords != null) cmdshowomitrecords.setEnabled(enable); // Action cmdsort = (Action) actions.get("cmdsort"); //$NON-NLS-1$ // if (cmdsort != null) cmdsort.setEnabled(enable); // Action cmddeleteallrecord = (Action) actions.get("cmddeleteallrecord"); //$NON-NLS-1$ // if (cmddeleteallrecord != null) cmddeleteallrecord.setEnabled(enable); // // Action cmdnextrecord = (Action) actions.get("cmdnextrecord"); //$NON-NLS-1$ // if (cmdnextrecord != null) cmdnextrecord.setEnabled(enable); // // Action cmdprevrecord = (Action) actions.get("cmdprevrecord"); //$NON-NLS-1$ // if (cmdprevrecord != null) cmdprevrecord.setEnabled(enable); if (fm instanceof SwingFormManager) { ((SwingFormManager)fm).enableCmds(enable); } //if plugins have added menus if (application.getImportMenu().getMenuComponents().length != 0) { Action a = actions.get("menuimportaction"); //$NON-NLS-1$ if (a != null) a.setEnabled(enable); } if (application.getExportMenu().getMenuComponents().length != 0) { Action a = actions.get("menuexportaction"); //$NON-NLS-1$ if (a != null) a.setEnabled(enable); } } /** * The shell for Cmds. This method executes the given Cmd in response to the given event (some Cmds look at the Event that invoke them, even though this is * discouraged). The Editor executes the Cmd in a safe environment so that buggy actions cannot crash the whole App. */ public void executeCmd(final ICmd c, final java.util.EventObject ie) { if (c == null) return; if (stopTime != 0 && System.currentTimeMillis() > stopTime) { JOptionPane.showMessageDialog(application.getMainApplicationFrame(), application.getI18NMessage("servoy.license.text"), application.getI18NMessage("servoy.license.label"), JOptionPane.WARNING_MESSAGE); //$NON-NLS-1$ //$NON-NLS-2$ } try { application.invokeLater(new Runnable() { public void run() { // //save any outstanding change,THIS ALSO DOES UI UPDATES IN 'saveData'!!!! // FormManager fm = application.getFormManager(); // if (fm != null) // { // IDataManipulator dm = fm.getCurrentMainDataManipulator(); // if (dm != null) dm.saveData();//make sure all data is saved on close(); // } UndoableEdit ue = c.doIt(ie); if (ue != null && undoManager != null && ue.canUndo()) { undoManager.addEdit(ue); } } }); } catch (java.lang.Throwable ex) { Debug.error("While executing " + c + //$NON-NLS-1$ " on event " + ie + //$NON-NLS-1$ " the following error occured:"); //$NON-NLS-1$ Debug.error(ex); } } private long stopTime = 0; public void setTrailMode(int time) { if (time != -1) { stopTime = System.currentTimeMillis() + time; } else //if (stopTime != 0) { stopTime = 0; } } private boolean autoOpenSolutionSelectDialog = true; public void setAutoOpenSolutionSelectDialog(boolean b) { autoOpenSolutionSelectDialog = b; } /** * Does assume that the registerd action is a ICmd */ public void executeRegisteredAction(String name) { Action action = actions.get(name.toLowerCase()); action.actionPerformed(new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "hmm")); //$NON-NLS-1$ // if (action != null && action instanceof ICmd) // { // executeCmd((ICmd)action,null); // } } /** * Returns the action todo the undo, when executed it does one step back in history when possible. */ public Action getUndoAction() { return undoAction; } /** * Return the action todo the redo, when executed it does one step forward when possible. */ public Action getRedoAction() { return redoAction; } public void undo() { if (undoManager != null && undoManager.canUndo()) { undoManager.undo(); } } public void redo() { if (undoManager != null && undoManager.canRedo()) { undoManager.redo(); } } public void addUndoableEdit(UndoableEdit undoableEdit) { if (undoableEdit != null && undoManager != null) { undoManager.addEdit(undoableEdit); } } public void flushCachedItems() { // actions = new HashMap(); to dangerous } /** * @see com.servoy.j2db.IManager#init() */ public void init() { //ignore } /* * (non-Javadoc) * * @see com.servoy.j2db.cmd.ICmdManager#refresh() */ public void i18nRefresh() { Iterator<Action> it = actions.values().iterator(); while (it.hasNext()) { MessageTextAction action = (MessageTextAction)it.next(); action.refresh(); } } }