/*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 05.05.2005
* Copyright (C) 2005 Dimitri Polivaev
*/
package freemind.controller.filter;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.filechooser.FileFilter;
import freemind.common.NamedObject;
import freemind.controller.Controller;
import freemind.controller.filter.condition.Condition;
import freemind.controller.filter.condition.ConditionNotSatisfiedDecorator;
import freemind.controller.filter.condition.ConjunctConditions;
import freemind.controller.filter.condition.DisjunctConditions;
import freemind.controller.filter.util.ExtendedComboBoxModel;
import freemind.main.Resources;
import freemind.main.Tools;
import freemind.modes.FreeMindFileDialog;
import freemind.modes.MapRegistry;
import freemind.modes.MindIcon;
import freemind.modes.MindMap;
import freemind.modes.ModeController;
import freemind.modes.attributes.AttributeRegistry;
/**
* @author dimitri
*
*/
public class FilterComposerDialog extends JDialog {
private static final Dimension maxButtonDimension = new Dimension(1000,
1000);
/**
* @author dimitri 06.05.2005
*/
private class AddConditionAction extends AbstractAction {
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
* )
*/
AddConditionAction() {
super();
Tools.setLabelAndMnemonic(this, Resources.getInstance()
.getResourceString("filter_add"));
}
public void actionPerformed(ActionEvent e) {
Condition newCond;
String value;
try {
value = getAttributeValue();
} catch (NullPointerException ex) {
return;
}
NamedObject simpleCond = (NamedObject) simpleCondition
.getSelectedItem();
boolean ignoreCase = caseInsensitive.isSelected();
Object selectedItem = attributes.getSelectedItem();
if (selectedItem instanceof NamedObject) {
NamedObject attribute = (NamedObject) selectedItem;
newCond = fc.getConditionFactory().createCondition(attribute,
simpleCond, value, ignoreCase);
} else {
String attribute = selectedItem.toString();
newCond = fc.getConditionFactory().createAttributeCondition(
attribute, simpleCond, value, ignoreCase);
}
DefaultComboBoxModel model = (DefaultComboBoxModel) conditionList
.getModel();
if (newCond != null)
model.addElement(newCond);
if (values.isEditable()) {
Object item = values.getSelectedItem();
if (item != null && !item.equals("")) {
values.removeItem(item);
values.insertItemAt(item, 0);
values.setSelectedIndex(0);
if (values.getItemCount() >= 10)
values.removeItemAt(9);
}
}
validate();
}
}
private class DeleteConditionAction extends AbstractAction {
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
* )
*/
DeleteConditionAction() {
super();
Tools.setLabelAndMnemonic(this, Resources.getInstance()
.getResourceString("filter_delete"));
}
public void actionPerformed(ActionEvent e) {
DefaultComboBoxModel model = (DefaultComboBoxModel) conditionList
.getModel();
final int minSelectionIndex = conditionList.getMinSelectionIndex();
int selectedIndex;
while (0 <= (selectedIndex = conditionList.getSelectedIndex())) {
model.removeElementAt(selectedIndex);
}
final int size = conditionList.getModel().getSize();
if (size > 0) {
conditionList
.setSelectedIndex(minSelectionIndex < size ? minSelectionIndex
: size - 1);
}
validate();
}
}
private class CreateNotSatisfiedConditionAction extends AbstractAction {
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
* )
*/
CreateNotSatisfiedConditionAction() {
super();
Tools.setLabelAndMnemonic(this, Resources.getInstance()
.getResourceString("filter_not"));
}
public void actionPerformed(ActionEvent e) {
int min = conditionList.getMinSelectionIndex();
if (min >= 0) {
int max = conditionList.getMinSelectionIndex();
if (min == max) {
Condition oldCond = (Condition) conditionList
.getSelectedValue();
Condition newCond = new ConditionNotSatisfiedDecorator(
oldCond);
DefaultComboBoxModel model = (DefaultComboBoxModel) conditionList
.getModel();
model.addElement(newCond);
validate();
}
}
}
}
private class CreateConjunctConditionAction extends AbstractAction {
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
* )
*/
CreateConjunctConditionAction() {
super();
Tools.setLabelAndMnemonic(this, Resources.getInstance()
.getResourceString("filter_and"));
}
public void actionPerformed(ActionEvent e) {
Object[] selectedValues = conditionList.getSelectedValues();
if (selectedValues.length < 2)
return;
Condition newCond = new ConjunctConditions(selectedValues);
DefaultComboBoxModel model = (DefaultComboBoxModel) conditionList
.getModel();
model.addElement(newCond);
validate();
}
}
private class CreateDisjunctConditionAction extends AbstractAction {
/*
* (non-Javadoc)
*
* @see
* java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
* )
*/
CreateDisjunctConditionAction() {
super();
Tools.setLabelAndMnemonic(this, Resources.getInstance()
.getResourceString("filter_or"));
}
public void actionPerformed(ActionEvent e) {
Object[] selectedValues = conditionList.getSelectedValues();
if (selectedValues.length < 2)
return;
Condition newCond = new DisjunctConditions(selectedValues);
DefaultComboBoxModel model = (DefaultComboBoxModel) conditionList
.getModel();
model.addElement(newCond);
validate();
}
}
private class ConditionListSelectionListener implements
ListSelectionListener, ListDataListener {
/*
* (non-Javadoc)
*
* @see
* javax.swing.event.ListSelectionListener#valueChanged(javax.swing.
* event.ListSelectionEvent)
*/
public void valueChanged(ListSelectionEvent e) {
if (conditionList.getMinSelectionIndex() == -1) {
btnNot.setEnabled(false);
btnAnd.setEnabled(false);
btnOr.setEnabled(false);
btnDelete.setEnabled(false);
return;
} else if (conditionList.getMinSelectionIndex() == conditionList
.getMaxSelectionIndex()) {
btnNot.setEnabled(true);
btnAnd.setEnabled(false);
btnOr.setEnabled(false);
btnDelete.setEnabled(true);
return;
} else {
btnNot.setEnabled(false);
btnAnd.setEnabled(true);
btnOr.setEnabled(true);
btnDelete.setEnabled(true);
}
}
public void intervalAdded(ListDataEvent e) {
conditionList.setSelectedIndex(e.getIndex0());
}
public void intervalRemoved(ListDataEvent e) {
}
public void contentsChanged(ListDataEvent e) {
}
}
private class ConditionListMouseListener extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
EventQueue.invokeLater(new Runnable() {
public void run() {
if (selectCondition()) {
dispose();
}
}
});
}
}
}
private class CloseAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
Object source = e.getSource();
if (source == btnOK || source == btnApply)
applyChanges();
if (source == btnOK || source == btnCancel)
dispose();
else
initInternalConditionModel();
}
}
static private class MindMapFilterFileFilter extends FileFilter {
static FileFilter filter = new MindMapFilterFileFilter();
public boolean accept(File f) {
if (f.isDirectory())
return true;
String extension = Tools.getExtension(f.getName());
if (extension != null) {
if (extension
.equals(FilterController.FREEMIND_FILTER_EXTENSION_WITHOUT_DOT)) {
return true;
} else {
return false;
}
}
return false;
}
public String getDescription() {
return Resources.getInstance().getResourceString(
"mindmaps_filter_desc");
}
}
protected FreeMindFileDialog getFileChooser() {
final ModeController modeController = fc.getMap().getModeController();
FreeMindFileDialog chooser = modeController
.getFileChooser(MindMapFilterFileFilter.filter);
return chooser;
}
private class SaveAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
FreeMindFileDialog chooser = getFileChooser();
chooser.setDialogTitle(Resources.getInstance().getResourceString(
"save_as"));
int returnVal = chooser.showSaveDialog(FilterComposerDialog.this);
if (returnVal != JFileChooser.APPROVE_OPTION) {// not ok pressed
return;
}
// |= Pressed O.K.
try {
File f = chooser.getSelectedFile();
String canonicalPath = f.getCanonicalPath();
final String suffix = '.' + FilterController.FREEMIND_FILTER_EXTENSION_WITHOUT_DOT;
if (!canonicalPath.endsWith(suffix)) {
canonicalPath = canonicalPath + suffix;
}
fc.saveConditions(internalConditionsModel, canonicalPath);
} catch (Exception ex) {
handleSavingException(ex);
}
}
private void handleSavingException(Exception ex) {
// TODO Auto-generated method stub
}
}
private class LoadAction implements ActionListener {
public void actionPerformed(ActionEvent e) {
FreeMindFileDialog chooser = getFileChooser();
int returnVal = chooser.showOpenDialog(FilterComposerDialog.this);
if (returnVal == JFileChooser.APPROVE_OPTION) {
try {
File theFile = chooser.getSelectedFile();
fc.loadConditions(internalConditionsModel,
theFile.getCanonicalPath());
} catch (Exception ex) {
handleLoadingException(ex);
}
{
}
}
}
private void handleLoadingException(Exception ex) {
// TODO Auto-generated method stub
}
}
private static final int NODE_POSITION = 0;
private static final int ICON_POSITION = 1;
private class SimpleConditionChangeListener implements ItemListener {
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
boolean considerValue = !simpleCondition.getSelectedItem()
.equals("filter_exist")
&& !simpleCondition.getSelectedItem().equals(
"filter_does_not_exist");
caseInsensitive.setEnabled(considerValue);
values.setEnabled(considerValue);
}
}
}
private class SelectedAttributeChangeListener implements ItemListener {
/*
* (non-Javadoc)
*
* @see
* javax.swing.event.ListSelectionListener#valueChanged(javax.swing.
* event.ListSelectionEvent)
*/
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
if (attributes.getSelectedIndex() == NODE_POSITION) {
simpleCondition.setModel(simpleNodeConditionComboBoxModel);
simpleCondition.setEnabled(true);
values.setEditable(true);
values.setEnabled(true);
nodes.setExtensionList(null);
values.setModel(nodes);
caseInsensitive.setEnabled(true);
return;
}
if (attributes.getSelectedIndex() == ICON_POSITION) {
simpleCondition.setModel(simpleIconConditionComboBoxModel);
simpleCondition.setEnabled(true);
values.setEditable(false);
values.setEnabled(true);
values.setModel(icons);
if (icons.getSize() >= 1) {
values.setSelectedIndex(0);
}
caseInsensitive.setEnabled(false);
return;
}
if (attributes.getSelectedIndex() > NODE_POSITION) {
final String attributeName = attributes.getSelectedItem()
.toString();
nodes.setExtensionList(registeredAttributes.getElement(
attributeName).getValues());
values.setModel(nodes);
if (values.getSelectedItem() != null) {
if (nodes.getSize() >= 1) {
values.setSelectedIndex(0);
} else {
values.setSelectedItem(null);
}
}
if (simpleCondition.getModel() != simpleAttributeConditionComboBoxModel) {
simpleCondition
.setModel(simpleAttributeConditionComboBoxModel);
simpleCondition.setSelectedIndex(0);
}
if (simpleCondition.getSelectedIndex() == 0) {
caseInsensitive.setEnabled(false);
values.setEnabled(false);
}
values.setEditable(true);
simpleCondition.setEnabled(true);
return;
}
}
}
}
private Controller c;
private FilterController fc;
private JList conditionList;
private JComboBox simpleCondition;
private JComboBox values;
private JComboBox attributes;
private FilterToolbar ft;
private JButton btnAdd;
private JButton btnNot;
private JButton btnAnd;
private JButton btnOr;
private JButton btnDelete;
private JCheckBox caseInsensitive;
private ExtendedComboBoxModel icons;
private ExtendedComboBoxModel nodes;
private AttributeRegistry registeredAttributes;
private DefaultComboBoxModel simpleNodeConditionComboBoxModel;
private DefaultComboBoxModel simpleIconConditionComboBoxModel;
private DefaultComboBoxModel simpleAttributeConditionComboBoxModel;
private ExtendedComboBoxModel filteredAttributeComboBoxModel;
private DefaultComboBoxModel internalConditionsModel;
private ComboBoxModel externalConditionsModel;
private JButton btnOK;
private JButton btnApply;
private JButton btnCancel;
private JButton btnSave;
private JButton btnLoad;
private ConditionListSelectionListener conditionListListener;
public FilterComposerDialog(Controller c, final FilterToolbar ft) {
super(c.getJFrame(), c.getResourceString("filter_dialog"));
this.c = c;
this.fc = c.getFilterController();
this.ft = ft;
final Box simpleConditionBox = Box.createHorizontalBox();
simpleConditionBox.setBorder(new EmptyBorder(5, 0, 5, 0));
getContentPane().add(simpleConditionBox, BorderLayout.NORTH);
attributes = new JComboBox();
filteredAttributeComboBoxModel = new ExtendedComboBoxModel(
new NamedObject[] {
Resources.getInstance().createTranslatedString(
"filter_node"),
Resources.getInstance().createTranslatedString(
"filter_icon") });
MapRegistry registry = c.getModel().getRegistry();
registeredAttributes = registry.getAttributes();
filteredAttributeComboBoxModel.setExtensionList(registeredAttributes
.getListBoxModel());
attributes.setModel(filteredAttributeComboBoxModel);
attributes.addItemListener(new SelectedAttributeChangeListener());
simpleConditionBox.add(Box.createHorizontalGlue());
simpleConditionBox.add(attributes);
attributes.setRenderer(fc.getConditionRenderer());
simpleNodeConditionComboBoxModel = new DefaultComboBoxModel(fc
.getConditionFactory().getNodeConditionNames());
simpleIconConditionComboBoxModel = new DefaultComboBoxModel(fc
.getConditionFactory().getIconConditionNames());
simpleCondition = new JComboBox();
simpleCondition.setModel(simpleNodeConditionComboBoxModel);
simpleCondition.addItemListener(new SimpleConditionChangeListener());
simpleConditionBox.add(Box.createHorizontalGlue());
simpleConditionBox.add(simpleCondition);
simpleCondition.setRenderer(fc.getConditionRenderer());
simpleAttributeConditionComboBoxModel = new DefaultComboBoxModel(fc
.getConditionFactory().getAttributeConditionNames());
values = new JComboBox();
nodes = new ExtendedComboBoxModel();
values.setModel(nodes);
simpleConditionBox.add(Box.createHorizontalGlue());
simpleConditionBox.add(values);
values.setRenderer(fc.getConditionRenderer());
values.setEditable(true);
icons = new ExtendedComboBoxModel();
icons.setExtensionList(registry.getIcons());
caseInsensitive = new JCheckBox();
simpleConditionBox.add(Box.createHorizontalGlue());
simpleConditionBox.add(caseInsensitive);
caseInsensitive.setText(Resources.getInstance().getResourceString(
"filter_ignore_case"));
final Box conditionButtonBox = Box.createVerticalBox();
conditionButtonBox.setBorder(new EmptyBorder(0, 10, 0, 10));
getContentPane().add(conditionButtonBox, BorderLayout.EAST);
btnAdd = new JButton(new AddConditionAction());
btnAdd.setMaximumSize(maxButtonDimension);
conditionButtonBox.add(Box.createVerticalGlue());
conditionButtonBox.add(btnAdd);
btnNot = new JButton(new CreateNotSatisfiedConditionAction());
conditionButtonBox.add(Box.createVerticalGlue());
btnNot.setMaximumSize(maxButtonDimension);
conditionButtonBox.add(btnNot);
btnNot.setEnabled(false);
btnAnd = new JButton(new CreateConjunctConditionAction());
conditionButtonBox.add(Box.createVerticalGlue());
btnAnd.setMaximumSize(maxButtonDimension);
conditionButtonBox.add(btnAnd);
btnAnd.setEnabled(false);
btnOr = new JButton(new CreateDisjunctConditionAction());
conditionButtonBox.add(Box.createVerticalGlue());
btnOr.setMaximumSize(maxButtonDimension);
conditionButtonBox.add(btnOr);
btnOr.setEnabled(false);
btnDelete = new JButton(new DeleteConditionAction());
btnDelete.setEnabled(false);
conditionButtonBox.add(Box.createVerticalGlue());
btnDelete.setMaximumSize(maxButtonDimension);
conditionButtonBox.add(btnDelete);
conditionButtonBox.add(Box.createVerticalGlue());
final Box controllerBox = Box.createHorizontalBox();
controllerBox.setBorder(new EmptyBorder(5, 0, 5, 0));
getContentPane().add(controllerBox, BorderLayout.SOUTH);
CloseAction closeAction = new CloseAction();
btnOK = new JButton();
Tools.setLabelAndMnemonic(btnOK, Resources.getInstance()
.getResourceString("ok"));
btnOK.addActionListener(closeAction);
btnOK.setMaximumSize(maxButtonDimension);
btnApply = new JButton();
Tools.setLabelAndMnemonic(btnApply, Resources.getInstance()
.getResourceString("apply"));
btnApply.addActionListener(closeAction);
btnApply.setMaximumSize(maxButtonDimension);
btnCancel = new JButton();
Tools.setLabelAndMnemonic(btnCancel, Resources.getInstance()
.getResourceString("cancel"));
btnCancel.addActionListener(closeAction);
btnCancel.setMaximumSize(maxButtonDimension);
controllerBox.add(Box.createHorizontalGlue());
controllerBox.add(btnOK);
controllerBox.add(Box.createHorizontalGlue());
controllerBox.add(btnApply);
controllerBox.add(Box.createHorizontalGlue());
controllerBox.add(btnCancel);
controllerBox.add(Box.createHorizontalGlue());
if (!c.getFrame().isApplet()) {
ActionListener saveAction = new SaveAction();
btnSave = new JButton();
Tools.setLabelAndMnemonic(btnSave, Resources.getInstance()
.getResourceString("save"));
btnSave.addActionListener(saveAction);
btnSave.setMaximumSize(maxButtonDimension);
ActionListener loadAction = new LoadAction();
btnLoad = new JButton();
Tools.setLabelAndMnemonic(btnLoad, Resources.getInstance()
.getResourceString("load"));
btnLoad.addActionListener(loadAction);
btnLoad.setMaximumSize(maxButtonDimension);
controllerBox.add(btnSave);
controllerBox.add(Box.createHorizontalGlue());
controllerBox.add(btnLoad);
controllerBox.add(Box.createHorizontalGlue());
}
conditionList = new JList();
conditionList
.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
conditionList.setCellRenderer(fc.getConditionRenderer());
conditionList.setLayoutOrientation(JList.VERTICAL);
conditionList.setAlignmentX(Component.LEFT_ALIGNMENT);
conditionListListener = new ConditionListSelectionListener();
conditionList.addListSelectionListener(conditionListListener);
conditionList.addMouseListener(new ConditionListMouseListener());
final JScrollPane conditionScrollPane = new JScrollPane(conditionList);
JLabel conditionColumnHeader = new JLabel(Resources.getInstance()
.getResourceString("filter_conditions"));
conditionColumnHeader.setHorizontalAlignment(JLabel.CENTER);
conditionScrollPane.setColumnHeaderView(conditionColumnHeader);
conditionScrollPane.setPreferredSize(new Dimension(500, 200));
getContentPane().add(conditionScrollPane, BorderLayout.CENTER);
Tools.addEscapeActionToDialog(this);
pack();
}
private String getAttributeValue() {
if (attributes.getSelectedIndex() == ICON_POSITION) {
MindIcon mi = (MindIcon) values.getSelectedItem();
return mi.getName();
}
Object item = values.getSelectedItem();
return item != null ? item.toString() : "";
}
/**
*/
void mapChanged(MindMap newMap) {
if (newMap != null) {
icons.setExtensionList(newMap.getRegistry().getIcons());
if (icons.getSize() >= 1 && values.getModel() == icons) {
values.setSelectedIndex(0);
} else {
values.setSelectedIndex(-1);
if (values.getModel() == icons) {
values.setSelectedItem(null);
}
}
if (attributes.getSelectedIndex() > 1)
attributes.setSelectedIndex(0);
registeredAttributes = newMap.getRegistry().getAttributes();
filteredAttributeComboBoxModel
.setExtensionList(registeredAttributes.getListBoxModel());
} else {
icons.setExtensionList(null);
values.setSelectedIndex(-1);
attributes.setSelectedIndex(0);
filteredAttributeComboBoxModel.setExtensionList(null);
}
}
private boolean selectCondition() {
int min = conditionList.getMinSelectionIndex();
if (min >= 0) {
int max = conditionList.getMinSelectionIndex();
if (min == max) {
applyChanges();
return true;
}
}
return false;
}
/**
*/
public void setSelectedItem(Object selectedItem) {
conditionList.setSelectedValue(selectedItem, true);
}
public void show() {
initInternalConditionModel();
super.show();
}
private void initInternalConditionModel() {
externalConditionsModel = fc.getFilterConditionModel();
if (internalConditionsModel == null) {
internalConditionsModel = new DefaultComboBoxModel();
internalConditionsModel.addListDataListener(conditionListListener);
conditionList.setModel(internalConditionsModel);
} else {
internalConditionsModel.removeAllElements();
}
int index = -1;
for (int i = 2; i < externalConditionsModel.getSize(); i++) {
final Object element = externalConditionsModel.getElementAt(i);
internalConditionsModel.addElement(element);
if (element == externalConditionsModel.getSelectedItem()) {
index = i - 2;
}
}
if (index >= 0) {
conditionList.setSelectedIndex(index);
} else {
conditionList.clearSelection();
}
}
private void applyChanges() {
internalConditionsModel.setSelectedItem(conditionList
.getSelectedValue());
internalConditionsModel.removeListDataListener(conditionListListener);
fc.setFilterConditionModel(internalConditionsModel);
internalConditionsModel = null;
}
}