/*
* #!
* Ontopia Vizigator
* #-
* Copyright (C) 2001 - 2013 The Ontopia Project
* #-
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* !#
*/
package net.ontopia.topicmaps.viz;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.basic.BasicArrowButton;
import javax.swing.text.JTextComponent;
import net.ontopia.topicmaps.core.TopicIF;
/**
* INTERNAL: A General Configuration frame for the VizDesktop
*/
public class GeneralConfigFrame extends JFrame {
private VizController controller;
private JColorChooser backgroundChooser;
private JRadioButton[] singleClickOptions;
private ButtonGroup singleClickGroup;
private JRadioButton[] doubleClickOptions;
private ButtonGroup doubleClickGroup;
private Vector includedTopicTypes;
private JList included;
private Vector excludedTopicTypes;
private JList excluded;
private JRadioButton[] localityOptions;
private ButtonGroup localityGroup;
private OSpinner motionSpinner;
public GeneralConfigFrame(VizController aController) {
super(Messages.getString("Viz.GeneralConfigWindowTitle"));
controller = aController;
this.build();
}
private void build() {
JTabbedPane tabbedPane = new JTabbedPane();
backgroundChooser = new JColorChooser();
// Setting #setPreviewPanel() to a new empty JPanel should
// remove the preview panel from use.
backgroundChooser.setPreviewPanel(new JPanel());
backgroundChooser.getSelectionModel().addChangeListener(
new ChangeListener() {
public void stateChanged(ChangeEvent e) {
Color c = backgroundChooser.getColor();
setPanelBackgroundColour(c);
}
}
);
tabbedPane
.addTab(
Messages.getString("Viz.GeneralConfigTitle"), null, this.createMainPanel(),
Messages.getString("Viz.GeneralConfigHoverHelp"));
tabbedPane
.addTab(
Messages.getString("Viz.BackgroundColourConfigTitle"), null, backgroundChooser, Messages.getString("Viz.BackgroundColourConfigHoverHelp"));
tabbedPane
.addTab(
Messages.getString("Viz.TopicTypeExclusion"), null, this.createTypeExcludePanel(),
Messages.getString("Viz.TopicTypeExclusionHoverHelp"));
this.getContentPane().add(tabbedPane);
this.pack();
this.initializeValues();
this.setResizable(false);
}
private JPanel createTypeExcludePanel() {
JPanel border = new JPanel();
border.setLayout(new GridBagLayout());
border.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.TopicTypeExclusion")));
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
c.gridheight = 1;
c.weightx = 1;
c.weighty = 1;
included = new JList();
included.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
included.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent anEvent) {
if (anEvent.getClickCount() == 2)
exclude((TopicListItem) included.getSelectedValue());
}
});
excluded = new JList();
excluded.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
excluded.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent anEvent) {
if (anEvent.getClickCount() == 2)
include((TopicListItem) excluded.getSelectedValue());
}
});
JScrollPane left = new JScrollPane(included);
left.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.IncludedTopicTypes")));
c.gridx = 0;
border.add(left, c);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.Y_AXIS));
buttonPanel.add(Box.createVerticalStrut(8));
BasicArrowButton includeButton = new BasicArrowButton(BasicArrowButton.EAST);
includeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent action) {
exclude((TopicListItem) included.getSelectedValue());
}
});
buttonPanel.add(includeButton);
BasicArrowButton excludeButton = new BasicArrowButton(BasicArrowButton.WEST);
excludeButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent action) {
include((TopicListItem) excluded.getSelectedValue());
}
});
buttonPanel.add(excludeButton);
c.gridx = 1;
border.add(buttonPanel, c);
JScrollPane right = new JScrollPane(excluded);
right.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.ExcludedTopicTypes")));
c.gridx = 2;
border.add(right, c);
return border;
}
/**
* Initialize the GUI values
*/
private void initializeValues() {
singleClickGroup.setSelected(singleClickOptions[controller
.getConfigurationManager().getGeneralSingleClick()].getModel(), true);
doubleClickGroup.setSelected(doubleClickOptions[controller
.getConfigurationManager().getGeneralDoubleClick()].getModel(), true);
backgroundChooser.setColor(controller.getConfigurationManager()
.getPanelBackgroundColour());
localityGroup.setSelected(localityOptions[controller
.getConfigurationManager().getGeneralLocalityAlgorithm()].getModel(), true);
initializeTopicLists();
}
protected void initializeTopicLists() {
Collection topics = controller.getAllTopicTypes();
this.excludedTopicTypes = new Vector(topics.size());
this.includedTopicTypes = new Vector(topics.size());
Iterator iterator = topics.iterator();
while (iterator.hasNext()) {
TopicIF type = (TopicIF) iterator.next();
if (controller.getConfigurationManager().isTypeExcluded(type)) this.excludedTopicTypes
.add(new TopicListItem(type, controller.getStringifier()));
else this.includedTopicTypes.add(new TopicListItem(type, controller.getStringifier()));
}
this.setListDate(included, includedTopicTypes);
this.setListDate(excluded, excludedTopicTypes);
}
protected void setPanelBackgroundColour(Color aColor) {
controller.setPanelBackgroundColour(aColor);
}
private JPanel createMainPanel() {
JPanel main = new JPanel(new GridLayout(0, 1));
main.add(createMouseButtonConfigurationPanel());
main.add(createHoverHelpPanel());
main.add(createLocalityPanel());
if (VizDebugUtils.ENABLE_MOTION_CONFIGURATION)
main.add(createMotionPanel());
main.add(createNameLengthPanel());
return main;
}
private Component createMouseButtonConfigurationPanel() {
// Single Click Options
singleClickOptions = new JRadioButton[2];
JPanel singleClickPanel = new JPanel(new GridLayout(0, 1));
singleClickPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.SingleClick")));
JRadioButton expandNode = this.createSingleClickRadioButton(Messages
.getString("Viz.ExpandNode"), VizTopicMapConfigurationManager.EXPAND_NODE);
singleClickPanel.add(expandNode);
singleClickOptions[VizTopicMapConfigurationManager.EXPAND_NODE] = expandNode;
JRadioButton setFocusNode = this.createSingleClickRadioButton(Messages
.getString("Viz.SetFocusNode"), VizTopicMapConfigurationManager.SET_FOCUS_NODE);
singleClickPanel.add(setFocusNode);
singleClickOptions[VizTopicMapConfigurationManager.SET_FOCUS_NODE] = setFocusNode;
//Group the radio buttons.
singleClickGroup = new ButtonGroup();
singleClickGroup.add(expandNode);
singleClickGroup.add(setFocusNode);
// Double click options
doubleClickOptions = new JRadioButton[3];
JPanel doubleClickPanel = new JPanel(new GridLayout(0, 1));
doubleClickPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.DoubleClick")));
expandNode = this.createDoubleClickRadioButton(Messages
.getString("Viz.ExpandNode"), VizTopicMapConfigurationManager.EXPAND_NODE);
doubleClickPanel.add(expandNode);
doubleClickOptions[VizTopicMapConfigurationManager.EXPAND_NODE] = expandNode;
setFocusNode = this.createDoubleClickRadioButton(Messages
.getString("Viz.SetFocusNode"), VizTopicMapConfigurationManager.SET_FOCUS_NODE);
doubleClickPanel.add(setFocusNode);
doubleClickOptions[VizTopicMapConfigurationManager.SET_FOCUS_NODE] = setFocusNode;
JRadioButton goToTopic = this.createDoubleClickRadioButton(Messages
.getString("Viz.GoToTopic"), VizTopicMapConfigurationManager.GO_TO_TOPIC);
doubleClickPanel.add(goToTopic);
doubleClickOptions[VizTopicMapConfigurationManager.GO_TO_TOPIC] = goToTopic;
//Group the radio buttons.
doubleClickGroup = new ButtonGroup();
doubleClickGroup.add(expandNode);
doubleClickGroup.add(setFocusNode);
doubleClickGroup.add(goToTopic);
JPanel border = new JPanel();
border.setLayout(new BoxLayout(border, BoxLayout.X_AXIS));
border.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.MouseButtons")));
border.add(singleClickPanel);
border.add(doubleClickPanel);
return border;
}
/**
* Allows the user to select how the locality is computed.
*/
private Component createLocalityPanel() {
// Locality Options
localityOptions = new JRadioButton[2];
JPanel localityPanel = new JPanel(new GridLayout(0, 1));
localityPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.LocalityAlgorithm")));
JRadioButton nodeOriented = createLocalityRadioButton(Messages
.getString("Viz.NodeOriented"), VizTopicMapConfigurationManager.NODE_ORIENTED);
localityPanel.add(nodeOriented);
localityOptions[VizTopicMapConfigurationManager.NODE_ORIENTED] = nodeOriented;
JRadioButton edgeOriented = createLocalityRadioButton(Messages
.getString("Viz.EdgeOriented"), VizTopicMapConfigurationManager.EDGE_ORIENTED);
localityPanel.add(edgeOriented);
localityOptions[VizTopicMapConfigurationManager.EDGE_ORIENTED] = edgeOriented;
//Group the radio buttons.
localityGroup = new ButtonGroup();
localityGroup.add(nodeOriented);
localityGroup.add(edgeOriented);
return localityPanel;
}
/**
* Allows the user to select how the locality is computed.
*/
private Component createMotionPanel() {
// Create checkbox that enables/disables motion killer (and the spinner).
JCheckBox enableMotionKiller = new JCheckBox(Messages
.getString("Viz.EnableMotionKiller"), controller
.getConfigurationManager().isMotionKillerEnabled());
enableMotionKiller.addActionListener(new ActionListener() {
private boolean currentValue = controller.getConfigurationManager()
.isMotionKillerEnabled();
public void actionPerformed(ActionEvent e) {
currentValue = !currentValue;
controller.setMotionKillerEnabled(currentValue);
motionSpinner.setEnabled(currentValue);
controller.getVizPanel().updateEnableMotionKillerMenuItem();
controller.getVizPanel()
.enableDisableMotionKillerMenuItem(currentValue);
}
});
// Create spinner that can change the motion killer delay (if enabled).
motionSpinner = new OSpinner();
motionSpinner.setEnabled(controller.getConfigurationManager()
.isMotionKillerEnabled());
motionSpinner.setPreferredSize(new Dimension(40, 20));
motionSpinner.setValue(controller.getConfigurationManager()
.getGeneralMotionKillerDelay());
motionSpinner.addPropertyChangeListener("value", new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
setMotionKillerDelay(((Integer) evt.getNewValue()).intValue());
}
});
// Create panel containing motion killer controls.
JPanel border = new JPanel();
border.setLayout(new FlowLayout(FlowLayout.LEFT));
border.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.MotionProperties")));
border.add(enableMotionKiller);
border.add(motionSpinner);
return border;
}
/**
* Allows the user to specify the maximum name length on nodes.
*/
private Component createNameLengthPanel() {
// Create checkbox that enables/disables motion killer (and the spinner).
JLabel text = new JLabel(Messages.getString("Viz.MaxTopicNameLength"));
// Create spinner that can change the motion killer delay (if enabled).
motionSpinner = new OSpinner();
motionSpinner.setPreferredSize(new Dimension(40, 20));
motionSpinner.setMax(50);
motionSpinner.setValue(controller.getConfigurationManager()
.getMaxTopicNameLength());
motionSpinner.addPropertyChangeListener("value",
new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
setMaxTopicNameLength(((Integer) evt.getNewValue()).intValue());
}
});
// Create panel containing name length controls.
JPanel border = new JPanel();
border.setLayout(new FlowLayout(FlowLayout.LEFT));
border.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.NameProperties")));
border.add(text);
border.add(motionSpinner);
return border;
}
private JRadioButton createSingleClickRadioButton(String title,
final int action) {
JRadioButton node = new JRadioButton(title);
node.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setSingleClick(action);
}
});
return node;
}
private JRadioButton createDoubleClickRadioButton(String title,
final int action) {
JRadioButton node = new JRadioButton(title);
node.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setDoubleClick(action);
}
});
return node;
}
private JRadioButton createLocalityRadioButton(String title,
final int action) {
JRadioButton node = new JRadioButton(title);
node.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setLocalityAlgorithm(action);
}
});
return node;
}
protected void setDoubleClick(int anAction) {
controller.setGeneralDoubleClick(anAction);
}
protected void setSingleClick(int action) {
controller.setGeneralSingleClick(action);
}
protected void setLocalityAlgorithm(int action) {
controller.setGeneralLocalityAlgorithm(action);
}
public void setMotionKillerDelay(int seconds) {
controller.setMotionKillerDelay(seconds);
}
public void setMaxTopicNameLength(int length) {
controller.setMaxTopicNameLength(length);
}
private JPanel createHoverHelpPanel() {
JPanel border = new JPanel();
border.setLayout(new BoxLayout(border, BoxLayout.Y_AXIS));
border.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.HoverHelpTitle")));
JCheckBox displayRolePopup = new JCheckBox(Messages
.getString("Viz.DisplayRoleHoverHelp"), controller
.getConfigurationManager().shouldDisplayRoleHoverHelp());
displayRolePopup.addActionListener(new ActionListener() {
private boolean currentValue = controller.getConfigurationManager()
.shouldDisplayRoleHoverHelp();
public void actionPerformed(ActionEvent e) {
currentValue = !currentValue;
controller.shouldDisplayRoleHoverHelp(currentValue);
}
});
border.add(displayRolePopup);
JCheckBox displayAssocScopedNames = new JCheckBox(Messages
.getString("Viz.DisplayAssocScopedNames"), controller
.getConfigurationManager().shouldDisplayScopedAssociationNames());
displayAssocScopedNames.addActionListener(new ActionListener() {
private boolean currentValue = controller.getConfigurationManager()
.shouldDisplayScopedAssociationNames();
public void actionPerformed(ActionEvent e) {
currentValue = !currentValue;
controller.shouldDisplayScopedAssociationNames(currentValue);
}
});
border.add(displayAssocScopedNames);
return border;
}
private void include(TopicListItem selected) {
if (selected != null) {
excludedTopicTypes.remove(selected);
setListDate(excluded, excludedTopicTypes);
includedTopicTypes.add(selected);
setListDate(included, includedTopicTypes);
controller.setTypeIncluded(selected.getTopic());
}
}
private void setListDate(JList list, Vector vector) {
sortCollection(vector);
list.setListData(vector);
}
private void exclude(TopicListItem selected) {
if (selected != null) {
includedTopicTypes.remove(selected);
setListDate(included, includedTopicTypes);
excludedTopicTypes.add(selected);
setListDate(excluded, excludedTopicTypes);
controller.setTypeExcluded(selected.getTopic());
}
}
private void sortCollection(List list) {
TopicListItem.sort(list);
}
}