/*FreeMind - A Program for creating and viewing Mindmaps *Copyright (C) 2006 Christian Foltin <christianfoltin@users.sourceforge.net> *See COPYING for Details * *This program 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. * *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 General Public License for more details. * *You should have received a copy of the GNU General Public License *along with this program; if not, write to the Free Software *Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*$Id: ManagePatternsPopupDialog.java,v 1.1.2.4.2.15 2008/07/17 19:16:32 christianfoltin Exp $*/ package accessories.plugins.dialogs; import java.awt.CardLayout; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Vector; import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.AbstractListModel; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.JSplitPane; import javax.swing.ListSelectionModel; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import com.jgoodies.forms.factories.ButtonBarFactory; import freemind.common.TextTranslator; import freemind.controller.StructuredMenuHolder; import freemind.controller.actions.generated.instance.ManageStyleEditorWindowConfigurationStorage; import freemind.controller.actions.generated.instance.Pattern; import freemind.main.Tools; import freemind.modes.MindMapNode; import freemind.modes.StylePatternFactory; import freemind.modes.mindmapmode.MindMapController; import freemind.modes.mindmapmode.dialogs.StylePatternFrame; import freemind.modes.mindmapmode.dialogs.StylePatternFrame.StylePatternFrameType; /** */ public class ManagePatternsPopupDialog extends JDialog implements TextTranslator, KeyListener { private static Pattern sLastSelectedPattern = null; private static final String STACK_PATTERN_FRAME = "PATTERN"; private static final String EMPTY_FRAME = "EMPTY_FRAME"; private Pattern mLastSelectedPattern = null; private final class PatternListSelectionListener implements ListSelectionListener { public void valueChanged(ListSelectionEvent e) { if (e.getValueIsAdjusting() || mIsDragging) return; // save old list: writePatternBackToModel(); JList theList = (JList) e.getSource(); if (theList.isSelectionEmpty()) { mCardLayout.show(mRightStack, EMPTY_FRAME); } else { int index = theList.getSelectedIndex(); Pattern p = mPatternListModel.getPatternAt(index); setLastSelectedPattern(p); // write pattern: mStylePatternFrame.setPatternList(mPatternListModel .getPatternList()); mStylePatternFrame.setPattern(p); mCardLayout.show(mRightStack, STACK_PATTERN_FRAME); } } } protected final class PatternListModel extends AbstractListModel { private final List mPatternList; // private final List mListeners; public PatternListModel(List patternList) { // we take a copy of the list as it may came from the patterns xml // element and would be read-only this.mPatternList = new Vector(patternList); // this.mListeners = new Vector(); } public int getSize() { return mPatternList.size(); } /** * @return the name of the pattern belonging to index. */ public Object getElementAt(int index) { return getPatternAt(index).getName(); // return // "<html><table width=\"100\"><tr><td>"+getPatternAt(index).getName()+"</td><td align=\"right\">TEST</td></tr></table></html>"; } /** * @return the pattern belonging to index. */ public Pattern getPatternAt(int index) { return ((Pattern) mPatternList.get(index)); } public List getPatternList() { return Collections.unmodifiableList(mPatternList); } public void removePattern(int index) { if (index < 0 || index >= mPatternList.size()) { throw new IllegalArgumentException( "try to delete in pattern list with an index out of range: " + index); } logger.info("Pattern " + ((Pattern) mPatternList.get(index)).getName() + " should be removed at " + index); mPatternList.remove(index); fireIntervalRemoved(mList, index, index); } public void addPattern(Pattern newPattern, int selectedIndex) { logger.info("Pattern " + newPattern.getName() + " should be added at " + selectedIndex); mPatternList.add(selectedIndex, newPattern); fireIntervalAdded(mList, selectedIndex, selectedIndex); } private void printPatterns() { int i = 0; for (Iterator iter = mPatternList.iterator(); iter.hasNext();) { Pattern pattern = (Pattern) iter.next(); logger.info("Pattern " + i + " = " + pattern.getName()); i++; } } public Pattern getPatternByName(String name) { for (Iterator iter = mPatternList.iterator(); iter.hasNext();) { Pattern pattern = (Pattern) iter.next(); if (pattern.getName().equals(name)) { return pattern; } } return null; } public void add(int i, Object object) { if (object instanceof String) { String patternName = (String) object; Pattern correspondingPattern = getPatternByName(patternName); if (correspondingPattern != null) { addPattern(correspondingPattern, i); } } } public void remove(int i) { removePattern(i); } } private static final String WINDOW_PREFERENCE_STORAGE_PROPERTY = "accessories.plugins.dialogs.ManagePatternsPopupDialog/window_positions"; public static final int CANCEL = -1; public static final int OK = 1; private int result = CANCEL; private javax.swing.JPanel jContentPane = null; private MindMapController mController; private JButton jCancelButton; private JButton jOKButton; private CardLayout mCardLayout; private JPanel mRightStack; private PatternListModel mPatternListModel; private JPopupMenu popupMenu; private StylePatternFrame mStylePatternFrame; private JList mList; private boolean mIsDragging = false; private accessories.plugins.dialogs.ArrayListTransferHandler mArrayListHandler; private JSplitPane mSplitPane; private static Logger logger = null; /** * This is the default constructor */ public ManagePatternsPopupDialog(JFrame caller, MindMapController controller) { super(caller); this.mController = controller; if (logger == null) { logger = mController.getFrame() .getLogger(this.getClass().getName()); } List patternList = new Vector(); try { patternList = StylePatternFactory.loadPatterns(controller .getPatternReader()); } catch (Exception e) { freemind.main.Resources.getInstance().logException(e); JOptionPane.showMessageDialog(this, getDialogTitle(), controller .getText("accessories/plugins/ManagePatterns.not_found"), JOptionPane.ERROR_MESSAGE); } initialize(patternList); } /** * This method initializes this * * * @return void */ private void initialize(List patternList) { this.setTitle(getDialogTitle()); JPanel contentPane = getJContentPane(patternList); this.setContentPane(contentPane); setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent we) { cancelPressed(); } }); Action cancelAction = new AbstractAction() { public void actionPerformed(ActionEvent arg0) { cancelPressed(); } }; Tools.addEscapeActionToDialog(this, cancelAction); // // recover latest pattern: int i = 0; if (sLastSelectedPattern != null) { for (Iterator iterator = mPatternListModel.getPatternList() .iterator(); iterator.hasNext();) { Pattern pattern = (Pattern) iterator.next(); if (pattern.getName().equals(sLastSelectedPattern.getName())) { mList.setSelectedIndex(i); break; } ++i; } } this.pack(); ManageStyleEditorWindowConfigurationStorage decorateDialog = (ManageStyleEditorWindowConfigurationStorage) mController .decorateDialog(this, WINDOW_PREFERENCE_STORAGE_PROPERTY); if (decorateDialog != null) { mSplitPane.setDividerLocation(decorateDialog.getDividerPosition()); } } /** */ private String getDialogTitle() { return mController .getText("accessories/plugins/ManagePatterns.dialog.title"); } private void close() { ManageStyleEditorWindowConfigurationStorage storage = new ManageStyleEditorWindowConfigurationStorage(); storage.setDividerPosition(mSplitPane.getDividerLocation()); mController.storeDialogPositions(this, storage, WINDOW_PREFERENCE_STORAGE_PROPERTY); this.dispose(); } private void okPressed() { result = OK; writePatternBackToModel(); close(); } private void cancelPressed() { result = CANCEL; close(); } /** * This method initializes jContentPane * * * @return javax.swing.JPanel */ private javax.swing.JPanel getJContentPane(List patternList) { if (jContentPane == null) { jContentPane = new javax.swing.JPanel(); jContentPane.setLayout(new GridBagLayout()); mList = new JList(); mArrayListHandler = new ArrayListTransferHandler(); mList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); mPatternListModel = new PatternListModel(patternList); mList.setModel(mPatternListModel); mList.setTransferHandler(mArrayListHandler); mList.setDragEnabled(true); mList.addListSelectionListener(new PatternListSelectionListener()); mList.addMouseMotionListener(new MouseMotionListener() { public void mouseDragged(MouseEvent pE) { // TODO Auto-generated method stub mIsDragging = true; } public void mouseMoved(MouseEvent pE) { // TODO Auto-generated method stub mIsDragging = false; } }); /* Some common action listeners */ ActionListener addPatternActionListener = new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { addPattern(actionEvent); } }; ActionListener fromNodesActionListener = new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { insertPatternFromNode(actionEvent); } }; ActionListener applyActionListener = new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { applyToNode(actionEvent); } }; /** Menu **/ JMenuBar menu = new JMenuBar(); StructuredMenuHolder menuHolder = new StructuredMenuHolder(); JMenu mainItem = new JMenu( mController.getText("ManagePatternsPopupDialog.Actions")); menuHolder.addMenu(mainItem, "main/actions/."); JMenuItem menuItemApplyPattern = new JMenuItem( mController.getText("ManagePatternsPopupDialog.apply")); menuItemApplyPattern.addActionListener(applyActionListener); menuHolder.addMenuItem(menuItemApplyPattern, "main/actions/apply"); JMenuItem menuItemAddPattern = new JMenuItem( mController.getText("ManagePatternsPopupDialog.add")); menuItemAddPattern.addActionListener(addPatternActionListener); menuHolder.addMenuItem(menuItemAddPattern, "main/actions/add"); JMenuItem menuItemPatternFromNodes = new JMenuItem( mController.getText("ManagePatternsPopupDialog.from_nodes")); menuItemPatternFromNodes.addActionListener(fromNodesActionListener); menuHolder.addMenuItem(menuItemPatternFromNodes, "main/actions/from_nodes"); menuHolder.updateMenus(menu, "main/"); this.setJMenuBar(menu); /* Popup menu */ popupMenu = new JPopupMenu(); // menuHolder.addMenuItem(new JPopupMenu.Separator()); JMenuItem menuItemApply = new JMenuItem( mController.getText("ManagePatternsPopupDialog.apply")); menuHolder.addMenuItem(menuItemApply, "popup/apply"); menuItemApply.addActionListener(applyActionListener); JMenuItem menuItemAdd = new JMenuItem( mController.getText("ManagePatternsPopupDialog.add")); menuHolder.addMenuItem(menuItemAdd, "popup/add"); menuItemAdd.addActionListener(addPatternActionListener); JMenuItem menuItemDuplicate = new JMenuItem( mController.getText("ManagePatternsPopupDialog.duplicate")); menuHolder.addMenuItem(menuItemDuplicate, "popup/duplicate"); menuItemDuplicate.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { duplicatePattern(actionEvent); } }); JMenuItem menuItemFromNodes = new JMenuItem( mController.getText("ManagePatternsPopupDialog.from_nodes")); menuHolder.addMenuItem(menuItemFromNodes, "popup/from_nodes"); menuItemFromNodes.addActionListener(fromNodesActionListener); menuHolder.addSeparator("popup/sep"); JMenuItem menuItemRemove = new JMenuItem( mController.getText("ManagePatternsPopupDialog.remove")); menuItemRemove.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent actionEvent) { removePattern(actionEvent); } }); menuHolder.addMenuItem(menuItemRemove, "popup/remove"); menuHolder.updateMenus(popupMenu, "popup/"); mList.addMouseListener(new MouseAdapter() { public void mouseReleased(MouseEvent me) { showPopup(mList, me); } /** For Linux */ public void mousePressed(MouseEvent me) { showPopup(mList, me); } private void showPopup(final JList mList, MouseEvent me) { // if right mouse button clicked (or me.isPopupTrigger()) if (me.isPopupTrigger() && !mList.isSelectionEmpty() && mList.locationToIndex(me.getPoint()) == mList .getSelectedIndex()) { popupMenu.show(mList, me.getX(), me.getY()); } } }); mCardLayout = new CardLayout(); mRightStack = new JPanel(mCardLayout); mRightStack.add(new JPanel(), EMPTY_FRAME); mStylePatternFrame = new StylePatternFrame(this, mController, StylePatternFrameType.WITH_NAME_AND_CHILDS); mStylePatternFrame.init(); mStylePatternFrame.addListeners(); mRightStack.add(new JScrollPane(mStylePatternFrame), STACK_PATTERN_FRAME); JScrollPane leftPane = new JScrollPane(mList); mSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, leftPane, mRightStack); jContentPane.add(mSplitPane, new GridBagConstraints(0, 0, 2, 1, 1.0, 8.0, GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0)); jContentPane.add(ButtonBarFactory.buildOKCancelBar( getJCancelButton(), getJOKButton()), new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); // jContentPane.add(getJOKButton(), new GridBagConstraints(1, 1, 1, // 1, // 1.0, 1.0, GridBagConstraints.EAST, GridBagConstraints.NONE, // new Insets(0, 0, 0, 0), 0, 0)); // jContentPane.add(getJCancelButton(), new GridBagConstraints(2, 1, // 1, 1, 1.0, 1.0, GridBagConstraints.EAST, // GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0)); getRootPane().setDefaultButton(getJOKButton()); } return jContentPane; } private void addPattern(ActionEvent actionEvent) { writePatternBackToModel(); setLastSelectedPattern(null); Pattern newPattern = new Pattern(); newPattern.setName(searchForNameForNewPattern()); int selectedIndex = mList.getSelectedIndex(); if (selectedIndex < 0) { selectedIndex = mList.getModel().getSize(); } mPatternListModel.addPattern(newPattern, selectedIndex); mList.setSelectedIndex(selectedIndex); } private void duplicatePattern(ActionEvent actionEvent) { int selectedIndex = mList.getSelectedIndex(); writePatternBackToModel(); setLastSelectedPattern(null); Pattern oldPattern = mPatternListModel.getPatternAt(selectedIndex); // deep copy: Pattern newPattern = (Pattern) Tools.deepCopy(oldPattern); newPattern.setName(searchForNameForNewPattern()); mPatternListModel.addPattern(newPattern, selectedIndex); mList.setSelectedIndex(selectedIndex); } private void insertPatternFromNode(ActionEvent actionEvent) { writePatternBackToModel(); setLastSelectedPattern(null); Pattern newPattern = StylePatternFactory.createPatternFromSelected( mController.getSelected(), mController.getSelecteds()); newPattern.setName(searchForNameForNewPattern()); int selectedIndex = mList.getSelectedIndex(); if (selectedIndex < 0) { selectedIndex = mList.getModel().getSize(); } mPatternListModel.addPattern(newPattern, selectedIndex); mList.setSelectedIndex(selectedIndex); } private void applyToNode(ActionEvent actionEvent) { int selectedIndex = mList.getSelectedIndex(); if (selectedIndex < 0) return; writePatternBackToModel(); setLastSelectedPattern(null); Pattern pattern = mPatternListModel.getPatternAt(selectedIndex); for (Iterator iterator = mController.getSelecteds().iterator(); iterator .hasNext();) { MindMapNode node = (MindMapNode) iterator.next(); mController.applyPattern(node, pattern); } } private String searchForNameForNewPattern() { // give it a good name: String newName = mController.getText("PatternNewNameProperty"); // collect names: Vector allNames = new Vector(); for (Iterator iter = mPatternListModel.getPatternList().iterator(); iter .hasNext();) { Pattern p = (Pattern) iter.next(); allNames.add(p.getName()); } String toGiveName = newName; int i = 1; while (allNames.contains(toGiveName)) { toGiveName = newName + i; ++i; } return toGiveName; } private void removePattern(ActionEvent actionEvent) { int selectedIndex = mList.getSelectedIndex(); setLastSelectedPattern(null); mPatternListModel.removePattern(selectedIndex); if (mPatternListModel.getSize() > selectedIndex) { mList.setSelectedIndex(selectedIndex); } else if (mPatternListModel.getSize() > 0 && selectedIndex >= 0) { mList.setSelectedIndex(selectedIndex - 1); } else { // empty mList.clearSelection(); } } /** * This method initializes jButton * * @return javax.swing.JButton */ private JButton getJOKButton() { if (jOKButton == null) { jOKButton = new JButton(); jOKButton.setAction(new AbstractAction() { public void actionPerformed(ActionEvent e) { okPressed(); } }); jOKButton.setText(mController .getText("ManagePatternsPopupDialog.Save")); } return jOKButton; } /** * This method initializes jButton1 * * @return javax.swing.JButton */ private JButton getJCancelButton() { if (jCancelButton == null) { jCancelButton = new JButton(); jCancelButton.setAction(new AbstractAction() { public void actionPerformed(ActionEvent e) { cancelPressed(); } }); Tools.setLabelAndMnemonic(jCancelButton, getText("cancel")); } return jCancelButton; } /** * @return Returns the result. */ public int getResult() { return result; } public String getText(String pKey) { return mController.getText(pKey); } public List getPatternList() { return mPatternListModel.getPatternList(); } private void writePatternBackToModel() { if (getLastSelectedPattern() != null) { // save pattern: Pattern pattern = getLastSelectedPattern(); Pattern resultPatternCopy = mStylePatternFrame.getResultPattern(); // check for name change: String oldPatternName = pattern.getName(); String newPatternName = resultPatternCopy.getName(); if (!(oldPatternName.equals(newPatternName))) { // now, let's check, whether or not it is still unique: for (Iterator iter = mPatternListModel.getPatternList() .iterator(); iter.hasNext();) { Pattern otherPattern = (Pattern) iter.next(); if (otherPattern == pattern) { // myself is not regarded: continue; } if (otherPattern.getName().equals(newPatternName)) { // duplicate found. What now? JOptionPane .showMessageDialog( this, mController .getText("ManagePatternsPopupDialog.DuplicateNameMessage")); } } } // no duplicates. We search for uses of the old name: for (Iterator iter = mPatternListModel.getPatternList().iterator(); iter .hasNext();) { Pattern otherPattern = (Pattern) iter.next(); if (otherPattern.getPatternChild() != null && oldPatternName.equals(otherPattern.getPatternChild() .getValue())) { // change to new name otherPattern.getPatternChild().setValue(newPatternName); } } mStylePatternFrame.getResultPattern(pattern); // Special case that a pattern that points to itself is renamed: if (pattern.getPatternChild() != null && oldPatternName.equals(pattern.getPatternChild() .getValue())) { pattern.getPatternChild().setValue(newPatternName); } } } /* * (non-Javadoc) * * @see java.awt.event.KeyListener#keyPressed(java.awt.event.KeyEvent) */ public void keyPressed(KeyEvent keyEvent) { // System.out.println("key pressed: " + keyEvent); switch (keyEvent.getKeyCode()) { case KeyEvent.VK_ESCAPE: keyEvent.consume(); cancelPressed(); break; } } /* * (non-Javadoc) * * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent) */ public void keyReleased(KeyEvent keyEvent) { // System.out.println("keyReleased: " + keyEvent); } /* * (non-Javadoc) * * @see java.awt.event.KeyListener#keyTyped(java.awt.event.KeyEvent) */ public void keyTyped(KeyEvent keyEvent) { // System.out.println("keyTyped: " + keyEvent); } public Pattern getLastSelectedPattern() { return mLastSelectedPattern; } public void setLastSelectedPattern(Pattern pLastSelectedPattern) { mLastSelectedPattern = pLastSelectedPattern; sLastSelectedPattern = pLastSelectedPattern; } }