/*FreeMind - A Program for creating and viewing Mindmaps
*Copyright (C) 2000-2006 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitri Polivaev and others.
*
*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.
*/
/*
* Created on 16.03.2004
*
*/
package accessories.plugins;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import accessories.plugins.dialogs.ChooseFormatPopupDialog;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import freemind.common.PropertyBean;
import freemind.common.PropertyControl;
import freemind.common.SeparatorProperty;
import freemind.common.TextTranslator;
import freemind.common.XmlBindingTools;
import freemind.controller.Controller;
import freemind.controller.actions.generated.instance.Pattern;
import freemind.controller.actions.generated.instance.Patterns;
import freemind.extensions.HookRegistration;
import freemind.modes.MindMap;
import freemind.modes.MindMapNode;
import freemind.modes.ModeController;
import freemind.modes.StylePatternFactory;
import freemind.modes.mindmapmode.MindMapController;
import freemind.modes.mindmapmode.hooks.PermanentMindMapNodeHookAdapter;
import freemind.preferences.FreemindPropertyContributor;
import freemind.preferences.FreemindPropertyListener;
import freemind.preferences.layout.OptionPanel;
/**
* @author foltin
*
*/
public class AutomaticLayout extends PermanentMindMapNodeHookAdapter {
private static final String AUTOMATIC_FORMAT_LEVEL = "automaticFormat_level";
/**
* Registers the property pages.
*
* @author foltin
*
*/
public static class Registration implements HookRegistration {
private AutomaticLayoutPropertyContributor mAutomaticLayoutPropertyContributor;
private final MindMapController modeController;
private static FreemindPropertyListener listener = null;
public Registration(ModeController controller, MindMap map) {
modeController = (MindMapController) controller;
}
static class MyFreemindPropertyListener implements
FreemindPropertyListener {
public void propertyChanged(String propertyName, String newValue,
String oldValue) {
if (propertyName.startsWith(AUTOMATIC_FORMAT_LEVEL)) {
patterns = null;
}
}
};
public void register() {
// add listener:
if (listener == null) {
listener = new MyFreemindPropertyListener();
}
Controller.addPropertyChangeListener(listener);
mAutomaticLayoutPropertyContributor = new AutomaticLayoutPropertyContributor(
modeController);
OptionPanel.addContributor(mAutomaticLayoutPropertyContributor);
}
public void deRegister() {
OptionPanel.removeContributor(mAutomaticLayoutPropertyContributor);
Controller.removePropertyChangeListener(listener);
}
}
/**
* Translates style pattern properties into strings.
* */
static class StylePropertyTranslator implements TextTranslator {
private final MindMapController controller;
StylePropertyTranslator(MindMapController controller) {
super();
this.controller = controller;
}
public String getText(String pKey) {
return controller.getText(pKey);
}
}
/**
* Currently not used. Is useful if you want to make single patterns
* changeable.
* */
public static class StylePatternProperty extends PropertyBean implements
PropertyControl, ActionListener {
String description;
String label;
String pattern;
JButton mButton;
private final TextTranslator mTranslator;
private final MindMapController mindMapController;
public StylePatternProperty(String description, String label,
TextTranslator pTranslator, MindMapController pController) {
super();
this.description = description;
this.label = label;
mTranslator = pTranslator;
mindMapController = pController;
mButton = new JButton();
mButton.addActionListener(this);
pattern = null;
}
public String getDescription() {
return description;
}
public String getLabel() {
return label;
}
public void setValue(String value) {
pattern = value;
Pattern resultPattern = getPatternFromString();
String patternString = StylePatternFactory.toString(resultPattern,
new StylePropertyTranslator(mindMapController));
mButton.setText(patternString);
mButton.setToolTipText(patternString);
}
public String getValue() {
return pattern;
}
public void layout(DefaultFormBuilder builder,
TextTranslator pTranslator) {
JLabel label = builder.append(pTranslator.getText(getLabel()),
mButton);
label.setToolTipText(pTranslator.getText(getDescription()));
// add "reset to standard" popup:
}
public void actionPerformed(ActionEvent arg0) {
// construct pattern:
Pattern pat = getPatternFromString();
ChooseFormatPopupDialog formatDialog = new ChooseFormatPopupDialog(
mindMapController.getFrame().getJFrame(),
mindMapController,
"accessories/plugins/AutomaticLayout.properties_StyleDialogTitle",
pat);
formatDialog.setModal(true);
formatDialog.setVisible(true);
// process result:
if (formatDialog.getResult() == ChooseFormatPopupDialog.OK) {
Pattern resultPattern = formatDialog.getPattern();
resultPattern.setName("dummy");
pattern = XmlBindingTools.getInstance().marshall(resultPattern);
setValue(pattern);
firePropertyChangeEvent();
}
}
private Pattern getPatternFromString() {
return StylePatternFactory.getPatternFromString(pattern);
}
public void setEnabled(boolean pEnabled) {
mButton.setEnabled(pEnabled);
}
}
public static class StylePatternListProperty extends PropertyBean implements
PropertyControl, ListSelectionListener {
String description;
String label;
String patterns;
JList mList;
boolean mDialogIsShown = false;
private final TextTranslator mTranslator;
private final MindMapController mindMapController;
private DefaultListModel mDefaultListModel;
public StylePatternListProperty(String description, String label,
TextTranslator pTranslator, MindMapController pController) {
super();
this.description = description;
this.label = label;
mTranslator = pTranslator;
mindMapController = pController;
mList = new JList();
mList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
mDefaultListModel = new DefaultListModel();
mList.setModel(mDefaultListModel);
mList.addListSelectionListener(this);
patterns = null;
}
public String getDescription() {
return description;
}
public String getLabel() {
return label;
}
public void setValue(String value) {
patterns = value;
Patterns resultPatterns = getPatternsFromString();
mDefaultListModel.clear();
int j = 1;
StylePropertyTranslator stylePropertyTranslator = new StylePropertyTranslator(
mindMapController);
for (Iterator i = resultPatterns.getListChoiceList().iterator(); i
.hasNext();) {
Pattern pattern = (Pattern) i.next();
mDefaultListModel.addElement(mTranslator.getText("level" + j)
+ ": "
+ StylePatternFactory.toString(pattern,
stylePropertyTranslator));
j++;
}
}
public String getValue() {
return patterns;
}
public void layout(DefaultFormBuilder builder,
TextTranslator pTranslator) {
JLabel label = builder.append(pTranslator.getText(getLabel()));
builder.append(new JLabel());
label.setToolTipText(pTranslator.getText(getDescription()));
builder.appendSeparator();
builder.append(new JScrollPane(mList), 3);
// builder.append(mList);
}
private Patterns getPatternsFromString() {
return StylePatternFactory.getPatternsFromString(patterns);
}
public void setEnabled(boolean pEnabled) {
mList.setEnabled(pEnabled);
}
public void valueChanged(ListSelectionEvent e) {
// construct pattern:
final Patterns pat = getPatternsFromString();
JList source = (JList) e.getSource();
if (source.getSelectedIndex() < 0)
return;
final Pattern choice = (Pattern) pat.getChoice(source
.getSelectedIndex());
final ChooseFormatPopupDialog formatDialog = new ChooseFormatPopupDialog(
mindMapController.getFrame().getJFrame(),
mindMapController,
"accessories/plugins/AutomaticLayout.properties_StyleDialogTitle",
choice);
// FIXME: What's that? (fc, 8,4,2008).
EventQueue.invokeLater(new Runnable() {
public void run() {
if (mDialogIsShown)
return;
mDialogIsShown = true;
try {
formatDialog.setModal(true);
formatDialog.setVisible(true);
// process result:
if (formatDialog.getResult() == ChooseFormatPopupDialog.OK) {
formatDialog.getPattern(choice);
patterns = XmlBindingTools.getInstance().marshall(
pat);
setValue(patterns);
firePropertyChangeEvent();
}
} finally {
mDialogIsShown = false;
}
}
});
}
}
private static final class AutomaticLayoutPropertyContributor implements
FreemindPropertyContributor {
private final MindMapController modeController;
public AutomaticLayoutPropertyContributor(
MindMapController modeController) {
this.modeController = modeController;
}
public List getControls(TextTranslator pTextTranslator) {
Vector controls = new Vector();
controls.add(new OptionPanel.NewTabProperty(
"accessories/plugins/AutomaticLayout.properties_PatternTabName"));
controls.add(new SeparatorProperty(
"accessories/plugins/AutomaticLayout.properties_PatternSeparatorName"));
controls.add(new StylePatternListProperty("level",
AUTOMATIC_FORMAT_LEVEL, pTextTranslator, modeController));
return controls;
}
}
private static Patterns patterns = null;
/**
*
*/
public AutomaticLayout() {
super();
}
private void setStyle(MindMapNode node) {
logger.finest("updating node id="
+ node.getObjectId(getMindMapController()) + " and text:"
+ node);
int depth = depth(node);
logger.finest("COLOR, depth=" + (depth));
reloadPatterns();
int myIndex = patterns.sizeChoiceList() - 1;
if (depth < patterns.sizeChoiceList())
myIndex = depth;
Pattern p = (Pattern) patterns.getChoice(myIndex);
getMindMapController().applyPattern(node, p);
}
private int depth(MindMapNode node) {
if (node.isRoot())
return 0;
return depth(node.getParentNode()) + 1;
}
/*
* (non-Javadoc)
*
* @see
* freemind.extensions.PermanentNodeHook#onAddChild(freemind.modes.MindMapNode
* )
*/
public void onAddChildren(MindMapNode newChildNode) {
logger.finest("onAddChildren " + newChildNode);
super.onAddChild(newChildNode);
setStyleRecursive(newChildNode);
}
/*
* (non-Javadoc)
*
* @see
* freemind.extensions.PermanentNodeHook#onUpdateChildrenHook(freemind.modes
* .MindMapNode)
*/
public void onUpdateChildrenHook(MindMapNode updatedNode) {
super.onUpdateChildrenHook(updatedNode);
setStyleRecursive(updatedNode);
}
/*
* (non-Javadoc)
*
* @see freemind.extensions.PermanentNodeHook#onUpdateNodeHook()
*/
public void onUpdateNodeHook() {
super.onUpdateNodeHook();
setStyle(getNode());
}
/*
* (non-Javadoc)
*
* @see freemind.extensions.NodeHook#invoke(freemind.modes.MindMapNode)
*/
public void invoke(MindMapNode node) {
super.invoke(node);
setStyleRecursive(node);
}
/** get styles from preferences: */
private void reloadPatterns() {
if (patterns == null) {
String property = getMindMapController().getFrame().getProperty(
AUTOMATIC_FORMAT_LEVEL);
patterns = StylePatternFactory.getPatternsFromString(property);
}
}
/**
*/
private void setStyleRecursive(MindMapNode node) {
logger.finest("setStyle " + node);
setStyle(node);
// recurse:
for (Iterator i = node.childrenUnfolded(); i.hasNext();) {
MindMapNode child = (MindMapNode) i.next();
invoke(child);
}
}
}