/* * Created on Feb 10, 2007 * * Copyright (c) 2007 Jens Gulden * * http://www.frinika.com * * This file is part of Frinika. * * Frinika is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * Frinika 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with Frinika; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.frinika.gui; import static com.frinika.localization.CurrentLocale.getMessage; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.JComponent; import com.frinika.project.ProjectContainer; import com.frinika.project.gui.ProjectFrame; /** * Abstract superclass for menu-actions that will pop-up a dialog (usually to * prompt options from the user) before actually performing the action. * * Note: The implementation is non-reentrant, because action-specific * parameters are to be stored in instance-variables to make them accessible * accross the different performXxx() methods. However, this is not considered * to be harmful as a menu-action is supposed to be invoked from a single-user * GUI, thus only one thread at a time runs through actionPerformed(). * * @see OptionsDialog * @see OptionsEditor * * @author Jens Gulden */ public abstract class AbstractDialogAction extends AbstractAction { protected ProjectFrame frame; protected String actionId; protected OptionsDialog dialog; protected boolean canceled; public AbstractDialogAction(ProjectFrame frame, String actionId) { super(getMessage(actionId)+"..."); this.frame = frame; this.actionId = actionId; } public void actionPerformed(ActionEvent e) { canceled = false; perform(); // /might use clone().perform() to make thread-safe, but not necessary) } public void cancel() { canceled = true; } public void perform() { performPrepare(); if (!canceled) { performDialog(); if (!canceled) { performUndoable(); } } } protected void performPrepare() { // nop, may be overwritten by subclasses } /** * Ask user for options, usually via modal GUI-dialog. * If cancel is set to true after this method returns, * no action will be taken. * The default implementation shows the modal options dialog, if * one is available, otherwise it does nothing (for commands that are * directly executed without asking options.) */ protected void performDialog() { // usually not overwritten by subclasses OptionsDialog dialog = getDialog(); if (dialog != null) { dialog.show(); } if (dialog.isCanceled()) { this.cancel(); } } protected void performUndoable() { // usually not overwritten by subclasses ProjectContainer project = frame.getProjectContainer(); project.getEditHistoryContainer().mark(getMessage(actionId)); performAction(); project.getEditHistoryContainer().notifyEditHistoryListeners(); } abstract protected void performAction(); public OptionsDialog getDialog() { if (this.dialog == null) { this.dialog = createDialog(); // auto-create on first get (avoids confusion with constructor-execution-order) } return this.dialog; } /** * Creates a dialog to ask for options. * Typically not overwritten by subclasses that use a gui-editor, * they provide an inner editor-component to the dialog instead via * createDialogContent(). Overwrite this method here if you need other kinds * of dialogs than one with OK/Cancel buttons. * * @return */ protected OptionsDialog createDialog() { JComponent content = createGUI(); if (content != null) { OptionsDialog d = new OptionsDialog(frame, content, getMessage(actionId)); return d; } else { return null; } } public ProjectFrame getProjectFrame() { return frame; } /** * Creates inner gui-editor of a dialog to show to the user. * The implementation may just return null, which makes * the class effectually behave as an AbstractAction without user-interaction. * * @return */ abstract protected JComponent createGUI(); }