/*
* #!
* 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.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Vector;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JFileChooser;
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.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.colorchooser.DefaultColorSelectionModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import net.ontopia.topicmaps.core.TopicIF;
import net.ontopia.topicmaps.nav.utils.comparators.TopicComparator;
import net.ontopia.utils.SimpleFileFilter;
import com.touchgraph.graphlayout.Node;
/**
* This class provides a display to allow the user to define which colours are
* used when displaying associations of this type.
*/
public class TypesConfigFrame extends JFrame implements ListSelectionListener {
public static final int UNDEFINED_EDGE_SHAPE = -1;
public static final int UNDEFINED_EDGE_SHAPE_WEIGHT = -1;
public static final int UNDEFINED_NODE_SHAPE_PADDING = -1;
public static final int UNDEFINED_NODE_SHAPE = -1;
private static String[] AVAILABLE_SIZES = { "9", "10", "11", "12", "14",
"16", "18", "20", "22", "24", "28", "36" };
public static TypesConfigFrame createAssociationTypeConfigFrame(
VizController controller, VizDesktop desktop) {
controller.loadAssociationTypes();
TypesConfigFrame frame = new TypesConfigFrame(controller, desktop);
frame.setAssociationTypeModel();
frame.build();
return frame;
}
public static TypesConfigFrame createTopicTypeConfigFrame(
VizController controller, VizDesktop desktop) {
controller.loadTopicTypes();
TypesConfigFrame frame = new TypesConfigFrame(controller, desktop);
frame.setTopicTypeModel();
frame.build();
return frame;
}
private JColorChooser chooser;
private VizController controller;
private ConfigurationModelIF model;
private TopicIF selectedType;
private JList typeList;
private JPanel colorChooserPanel;
boolean ignoreSelection = false;
private ButtonGroup buttonGroup; // Shape buttons
private ButtonGroup filterGroup; // Filter buttons
private JTextField filenameField;
private JRadioButton[] shapeMap; // Maps buttons to models
private JRadioButton[] filterMap; // Maps buttons to models
private JSlider weight;
private JList fontList;
private JCheckBox bold;
private JCheckBox italic;
private DefaultColorSettingCheckBox defaultColorSettingCheckbox;
private JList sizeList;
private String lastIconPath;
private JButton clearButton;
private VizDesktop desktop;
// Topic type shape radio buttons.
private JRadioButton circle;
private JRadioButton ellipse;
private JRadioButton rectangle;
private JRadioButton round;
// Association type shape radio buttons.
private JRadioButton bowtie;
private JRadioButton line;
private JRadioButton unselect;
private JRadioButton filterIn;
private JRadioButton filterOut;
private JRadioButton filterDefault;
private JButton defaultButton;
private TypesConfigFrame(VizController controller, VizDesktop desktop) {
super();
this.controller = controller;
this.desktop = desktop;
unselect = new JRadioButton();
unselect.setVisible(false);
}
private void build() {
setTitle(model.getTitle());
// populate JList
typeList = new JList();
initializeTypeList();
// Set the first
typeList.setSelectedIndex(0);
selectedType = ((TopicListItem)typeList.getSelectedValue()).getTopic();
// setup UI
getContentPane().setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
typeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
typeList.addListSelectionListener(this);
JScrollPane scrlPane = new JScrollPane(typeList);
getContentPane().add(scrlPane, c);
JTabbedPane tabbedPane = new JTabbedPane();
colorChooserPanel = createColorChooserPanel();
tabbedPane
.addTab(
Messages.getString("Viz.StylingConfigTitle"), null,
createGeneralConfigPanel(),
Messages.getString("Viz.StylingConfigHoverHelp"));
tabbedPane
.addTab(
Messages.getString("Viz.ColourConfigTitle"), null,
colorChooserPanel,
Messages.getString("Viz.ColourConfigHoverHelp"));
tabbedPane
.addTab(
Messages.getString("Viz.FontConfigTitle"), null,
createFontSelectionPanel(),
Messages.getString("Viz.FontConfigHoverHelp"));
tabbedPane
.addTab(Messages.getString("Viz.TypeFilter"), null,
createFilterSelectionPanel(),
Messages.getString("Viz.FilterConfigHoverHelp"));
JPanel parent = new JPanel();
parent.setLayout(new BoxLayout(parent, BoxLayout.Y_AXIS));
parent.add(tabbedPane);
parent.add(createDefaultPanel());
getContentPane().add(parent, c);
pack();
setResizable(false);
defaultColorSettingCheckbox.update();
}
private JPanel createDefaultPanel() {
JPanel retVal = new JPanel();
retVal.setLayout(new BoxLayout(retVal, BoxLayout.X_AXIS));
defaultButton = new JButton(Messages
.getString("Viz.UseDefaultSettings"));
defaultButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
VizTopicMapConfigurationManager confMan = controller
.getConfigurationManager();
if (getUsingTopicModel()) {
// Remove color autogenerated setting from type.
confMan.removeOccurence(selectedType,
confMan.getTopicTypeColorAutogeneratedTopic());
// Remove color setting from topic type.
controller.setColorToDefault(selectedType, true);
// Remove font setting from topic type.
controller.setFontToDefault(selectedType, true);
setSelectedFont(controller.getTypeFont(selectedType));
// Remove icon setting from topic type.
controller.setTypeIconFilename(selectedType, null);
// Remove shape padding setting from topic type.
setSelectedWeight(model.getWeight(controller, confMan.defaultType));
controller.setTopicTypeShapePadding(selectedType,
UNDEFINED_NODE_SHAPE_PADDING);
// Remove shape setting from topic type.
unselectShapeRadioButtons();
controller.setTopicTypeShape(selectedType, UNDEFINED_NODE_SHAPE);
} else {
// Remove color autogenerated setting from type.
confMan.removeOccurence(selectedType,
confMan.getAssociationTypeColorAutogeneratedTopic());
// Remove color setting from association type.
controller.setColorToDefault(selectedType, false);
// Remove font setting from association type.
controller.setFontToDefault(selectedType, false);
setSelectedFont(controller.getTypeFont(selectedType));
// Remove line weight setting from type.
setSelectedWeight(model.getWeight(controller,
confMan.defaultAssociationType));
controller.setAssociationTypeLineWeight(selectedType,
UNDEFINED_EDGE_SHAPE_WEIGHT);
// Remove shape setting from type.
unselectShapeRadioButtons();
controller.setAssociationTypeShape(selectedType, UNDEFINED_EDGE_SHAPE);
}
// Make the appropriate font selection (or no selection, as the case may be)
// in the font selection interface.
updateFontSelection();
}
});
retVal.add(defaultButton);
return retVal;
}
private boolean getUsingTopicModel() {
return model instanceof TopicTypeConfigurationModel;
}
public class DefaultColorSettingCheckBox extends JCheckBox {
public DefaultColorSettingCheckBox() {
super(Messages.getString("Viz.OverrideRandomColors"));
setupCheckBox();
}
public void setupCheckBox() {
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
VizTopicMapConfigurationManager confMan = controller
.getConfigurationManager();
boolean defaultSelected = selectedType == confMan.defaultType ||
selectedType == confMan.defaultAssociationType;
if (defaultSelected) {
handleDefaultSelection();
} else {
handleRegularSelection();
}
}
});
}
private void handleDefaultSelection() {
VizTopicMapConfigurationManager confMan = controller
.getConfigurationManager();
TopicIF type = getUsingTopicModel() ? confMan.defaultType
: confMan.defaultAssociationType;
confMan.setOccurenceValue(type, confMan.getOverrideColorsTopic(),
isSelected());
Color c = getModelColor();
// Now get back the old color to (event will get triggered).
chooser.setColor(c);
}
private void handleRegularSelection() {
VizTopicMapConfigurationManager confMan = controller
.getConfigurationManager();
boolean selected = isSelected();
if (!selected) {
chooser.setColor(chooser.getColor());
return;
}
// Override (or not, pending selected) this color with default color.
confMan.setOccurenceValue(selectedType, getUsingTopicModel()
? confMan.getTopicTypeColorAutogeneratedTopic()
: confMan.getAssociationTypeColorAutogeneratedTopic(), selected);
// If the default type overrides automatic colours, get rid of old color.
// This overrides color setting permanently.
if (confMan.getUsesDefault(selectedType, getUsingTopicModel()))
confMan.removeOccurrence(selectedType,
confMan.getTopicTypeColorTopic());
// Update selectedType with appropriate (default) color.
Color color = getUsingTopicModel()
? controller.getTopicTypeColor(confMan.defaultType)
: controller.getAssociationTypeColor(confMan.defaultAssociationType);
controller.updateViewTypeColor(selectedType, color);
}
private void update() {
VizTopicMapConfigurationManager confMan = controller
.getConfigurationManager();
// Check if this is a default type or a regular (proper) type.
boolean useDefaultMode = selectedType == confMan.defaultType
|| selectedType == confMan.defaultAssociationType;
boolean selected;
if (useDefaultMode)
// The (un)checked state of the default type takes it's value from the
// configuration. With no given value, use unchecked (false) as default.
// So, by default it doesn't override autogenerated color values.
selected = confMan.defaultOverrides(getUsingTopicModel());
else
// The (un)checked state of proper types are checked by default.
// So, by default they do let the default color value toke precedence
// when the default overrides autogenerated color values.
selected = confMan.getUsesDefault(selectedType, getUsingTopicModel());
setText(Messages.getString(useDefaultMode
? "Viz.OverrideRandomColors" : "Viz.UseDefaultColor"));
setSelected(selected);
}
}
private Color getModelColor() {
return model.getColor(controller, selectedType);
}
/**
* Makes sure fireStateChanged() is called whenever there's been a color
* selection. This ensures default color is correctly overridden when an
* old default color is selected.
*/
public class VizColorSelectionModel extends DefaultColorSelectionModel {
public void setSelectedColor(Color color) {
super.setSelectedColor(color);
if (color != null && getSelectedColor().equals(color))
fireStateChanged();
}
}
protected JPanel createColorChooserPanel() {
JPanel parent = new JPanel(new BorderLayout());
chooser = new JColorChooser(new VizColorSelectionModel());
// Setting #setPreviewPanel() to a new empty JPanel should
// remove the preview panel from use.
chooser.setPreviewPanel(new JPanel());
chooser.getSelectionModel().addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if (typeList.getSelectedIndex() == -1) return;
Color c = chooser.getColor();
controller.setTypeColor(selectedType, c);
if (desktop != null) // LMG 2008-07-17: why not via controller?
desktop.setNewTypeColor(selectedType, c);
// Make default colour setting checkbox take correct (un)checked value.
defaultColorSettingCheckbox.update();
}
});
parent.add(chooser, BorderLayout.NORTH);
defaultColorSettingCheckbox = new DefaultColorSettingCheckBox();
parent.add(defaultColorSettingCheckbox, BorderLayout.SOUTH);
return parent;
}
/**
* Initialize the list of topic types.
*/
protected void initializeTypeList() {
Vector ttypes = new Vector();
Collection graphtypes = model.getListItems(controller);
// sort the topics
graphtypes = new ArrayList(graphtypes);
Collections.sort((java.util.List) graphtypes, new TopicComparator());
Iterator gtypes = graphtypes.iterator();
while (gtypes.hasNext()) {
TopicIF t = (TopicIF) gtypes.next();
if (t == controller.getConfigurationManager().defaultType)
ttypes.add(new TopicListItem(t, Messages.getString("Viz.DefaultType")));
else if (t == controller.getConfigurationManager().defaultAssociationType)
ttypes.add(new TopicListItem(t, Messages.getString("Viz.DefaultType")));
else if (t != null)
ttypes.add(new TopicListItem(t, controller.getStringifier()));
}
model.addAdditionalItems(ttypes);
typeList.setListData(ttypes);
}
/**
* Convert an array of font names to an array of alphabetically ordered font
* family names.
* @param names The font names.
* @return The font family names (without duplicates) of all the font names.
*/
private String[] toFamilyNames(String names[]) {
SortedSet familyNames = new TreeSet();
for (int i = 0; i < names.length; i++) {
familyNames.add(new Font(names[i], 12, Font.PLAIN).getFamily());
}
String familyNamesArray[] = new String[familyNames.size()];
familyNames.toArray(familyNamesArray);
return familyNamesArray;
}
private JPanel createFontSelectionPanel() {
JPanel parent = new JPanel(new BorderLayout());
GraphicsEnvironment g = GraphicsEnvironment.getLocalGraphicsEnvironment();
// Note: Despite the name of the method "getAvailableFontFamilyNames", it
// actually returns the font names, and not the font family names.
// The method "toFamilyNames" solves this, by generating a list of the
// corresponding font names.
String[] fonts = g.getAvailableFontFamilyNames();
fonts = toFamilyNames(fonts);
JPanel details = new JPanel(new BorderLayout());
JPanel fontPanel = new JPanel(new BorderLayout());
fontPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.FontBorderTitle")));
fontList = new JList(fonts);
fontList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
JScrollPane fontpane = new JScrollPane(fontList);
fontList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
// Only handle the change in selection when the user has finally made
// his selection !
if (e.getValueIsAdjusting() == true) return;
buildAndSetFont();
}
});
fontpane.setBorder(BorderFactory.createEtchedBorder());
fontPanel.add(fontpane);
parent.add(fontPanel);
JPanel sizePanel = new JPanel(new BorderLayout());
sizePanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.FontSizeBorderTitle")));
sizeList = new JList(AVAILABLE_SIZES);
sizeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
sizeList.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
// Only handle the change in selection when the user has finally made
// his selection !
if (e.getValueIsAdjusting() == true) return;
buildAndSetFont();
}
});
JScrollPane sizePane = new JScrollPane(sizeList);
sizePane.setBorder(BorderFactory.createEtchedBorder());
sizePanel.add(sizePane);
JPanel attributes = new JPanel(new GridLayout(1, 2));
attributes.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages
.getString("Viz.FontAttributesBorderTitle")));
bold = new JCheckBox(Messages.getString("Viz.FontBold"));
bold.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
buildAndSetFont();
}
});
italic = new JCheckBox(Messages.getString("Viz.FontItalic"));
italic.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
buildAndSetFont();
}
});
attributes.add(bold);
attributes.add(italic);
details.add(sizePanel, BorderLayout.CENTER);
details.add(attributes, BorderLayout.SOUTH);
parent.add(details, BorderLayout.EAST);
return parent;
}
/**
* Build a new font object from the GUI and assign it
*/
protected void buildAndSetFont() {
if (typeList.getSelectedValue() == null) return;
// We need @ignoreSelection since we cannot set the current
// font without signalling the font changes callbacks
if (ignoreSelection) return;
String name = (String) fontList.getSelectedValue();
String sizeString = (String) sizeList.getSelectedValue();
boolean isBold = bold.isSelected();
boolean isItalic = italic.isSelected();
if (name == null || sizeString == null) {
Font fallbackFont = controller.getTypeFont(selectedType);
if (name == null && sizeString == null && !isBold)
isBold = fallbackFont.isBold();
if (name == null && sizeString == null && !isItalic)
isItalic = fallbackFont.isItalic();
if (name == null) {
name = fallbackFont.getFamily();
fontList.setSelectedValue(name, true);
}
if (sizeString == null) {
sizeString = Integer.toString(fallbackFont.getSize());
sizeList.setSelectedValue(sizeString, true);
}
}
int style = Font.PLAIN;
if (isBold) style = style | Font.BOLD;
if (isItalic) style = style | Font.ITALIC;
controller.setTypeFont(selectedType, new Font(name, style, Integer
.parseInt(sizeString)));
}
public void buildAssociationTypeGeneralConfigPanel(JPanel config) {
config.add(createAssociationTypeShapePanel());
config.add(createIconPanel());
}
public void buildTopicTypeGeneralConfigPanel(JPanel config) {
config.add(createTopicTypeShapePanel());
config.add(createIconPanel());
}
private JPanel createAssociationTypeShapePanel() {
// Make the size of the shapeMap one bigger than the number of radio buttons
shapeMap = new JRadioButton[3];
JPanel shapePanel = new JPanel(new GridLayout(0, 1));
shapePanel.setBorder(BorderFactory
.createTitledBorder(BorderFactory.createEtchedBorder(), Messages
.getString("Viz.ObjectShapeBorderTitle")));
bowtie = new JRadioButton(Messages
.getString("Viz.ObjectShapeBowtie"));
bowtie.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setShape(TMRoleEdge.SHAPE_BOWTIE);
}
});
shapePanel.add(bowtie);
shapeMap[TMRoleEdge.SHAPE_BOWTIE] = bowtie;
line = new JRadioButton(Messages
.getString("Viz.ObjectShapeLine"));
line.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setShape(TMRoleEdge.SHAPE_LINE);
}
});
shapePanel.add(line);
shapeMap[TMRoleEdge.SHAPE_LINE] = line;
//Group the radio buttons.
buttonGroup = new ButtonGroup();
buttonGroup.add(bowtie);
buttonGroup.add(line);
buttonGroup.add(unselect);
shapePanel.add(createWeightPanel(
Messages.getString("Viz.ObjectShapeWeight"), 1,
TMRoleEdge.DEFAULT_LINE_WEIGHT * 3));
return shapePanel;
}
private JPanel createAssociationTypeFilterPanel() {
// Make the size of the shapeMap one bigger than the number of radio buttons
filterMap = new JRadioButton[4];
JPanel filterPanel = new JPanel(new GridLayout(0, 1));
filterPanel.setBorder(BorderFactory
.createTitledBorder(BorderFactory.createEtchedBorder(),
Messages.getString("Viz.TypeFilter")));
filterIn = new JRadioButton(Messages.getString("Viz.FilterIn"));
filterIn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setFilter(VizTopicMapConfigurationManager.FILTER_IN);
}
});
filterPanel.add(filterIn);
filterMap[VizTopicMapConfigurationManager.FILTER_IN] = filterIn;
filterOut = new JRadioButton(Messages.getString("Viz.FilterOut"));
filterOut.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setFilter(VizTopicMapConfigurationManager.FILTER_OUT);
}
});
filterPanel.add(filterOut);
filterMap[VizTopicMapConfigurationManager.FILTER_OUT] = filterOut;
filterDefault = new JRadioButton(Messages
.getString("Viz.UseDefaultFilterSetting"));
filterDefault.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setFilter(VizTopicMapConfigurationManager.FILTER_DEFAULT);
}
});
filterPanel.add(filterDefault);
filterMap[VizTopicMapConfigurationManager.FILTER_DEFAULT] = filterDefault;
//Group the radio buttons.
filterGroup = new ButtonGroup();
filterGroup.add(filterIn);
filterGroup.add(filterOut);
filterGroup.add(filterDefault);
filterGroup.add(unselect);
return filterPanel;
}
private Box createWeightPanel(String title, int min, int max) {
Box weightPanel = new Box(BoxLayout.X_AXIS);
weightPanel.add(Box.createHorizontalStrut(10));
weightPanel.add(new JLabel(title));
weightPanel.add(Box.createHorizontalStrut(10));
weight = new JSlider(JSlider.HORIZONTAL, min, max, 1);
weight.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
setWeight(((JSlider) e.getSource()).getValue());
}
});
weightPanel.add(weight);
weightPanel.add(Box.createHorizontalStrut(10));
return weightPanel;
}
private JPanel createGeneralConfigPanel() {
JPanel config = new JPanel(new GridLayout(0, 1));
model.buildGeneralConfigPanel(this, config);
return config;
}
private JPanel createFilterSelectionPanel() {
JPanel config = new JPanel(new GridLayout(0, 1));
config.add(createAssociationTypeFilterPanel());
updateSelectedFilter();
return config;
}
private JPanel createIconPanel() {
JPanel iconPanel = new JPanel();
iconPanel.setLayout(new BoxLayout(iconPanel, BoxLayout.X_AXIS));
iconPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory
.createEtchedBorder(), Messages.getString("Viz.IconBorderTitle")));
iconPanel.add(Box.createHorizontalStrut(10));
iconPanel.add(new JLabel(Messages.getString("Viz.IconFilename")));
iconPanel.add(Box.createHorizontalStrut(10));
filenameField = new JTextField(15);
// Stupid ... stupid ... stupid ... This is the only way I would get the components to layout correctly !
filenameField.setMaximumSize(new Dimension((int) (filenameField
.getMaximumSize().getWidth()), (int) (filenameField.getPreferredSize()
.getHeight())));
filenameField.setEditable(false);
iconPanel.add(filenameField);
iconPanel.add(Box.createHorizontalStrut(10));
// Must be final to refer to in inner class.
final Component thisComponent = this;
JButton fileButton = new JButton(Messages.getString("Viz.IconBrowseButton"));
fileButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
String filename = promptForFile();
if (filename != null) {
setSelectedIconFilename(filename);
setIconFilename(filename);
}
} catch (java.security.AccessControlException exception) {
ErrorDialog.showError(thisComponent, Messages.getString(
"Viz.FileBrowseFailure"));
}
}
});
iconPanel.add(fileButton);
iconPanel.add(Box.createHorizontalStrut(10));
clearButton = new JButton(Messages.getString("Viz.IconClear"));
clearButton.setEnabled(false);
clearButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent anE) {
setSelectedIconFilename(null);
setIconFilename(null);
}
});
iconPanel.add(clearButton);
return iconPanel;
}
private JPanel createTopicTypeShapePanel() {
// Make the size of the shapeMap one bigger than the number of
// radio buttons
shapeMap = new JRadioButton[5];
JPanel shapePanel = new JPanel(new GridLayout(0, 1));
shapePanel.setBorder(BorderFactory
.createTitledBorder(BorderFactory.createEtchedBorder(), Messages
.getString("Viz.ObjectShapeBorderTitle")));
circle = new JRadioButton(Messages
.getString("Viz.ObjectShapeCircle"));
circle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setShape(Node.TYPE_CIRCLE);
}
});
shapePanel.add(circle);
shapeMap[Node.TYPE_CIRCLE] = circle;
ellipse = new JRadioButton(Messages
.getString("Viz.ObjectShapeEllipse"));
ellipse.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setShape(Node.TYPE_ELLIPSE);
}
});
shapePanel.add(ellipse);
shapeMap[Node.TYPE_ELLIPSE] = ellipse;
rectangle = new JRadioButton(Messages
.getString("Viz.ObjectShapeRectangle"));
rectangle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setShape(Node.TYPE_RECTANGLE);
}
});
shapePanel.add(rectangle);
shapeMap[Node.TYPE_RECTANGLE] = rectangle;
round = new JRadioButton(Messages
.getString("Viz.ObjectShapeRoundRectangle"));
round.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setShape(Node.TYPE_ROUNDRECT);
}
});
shapePanel.add(round);
shapeMap[Node.TYPE_ROUNDRECT] = round;
// Group the radio buttons.
buttonGroup = new ButtonGroup();
buttonGroup.add(circle);
buttonGroup.add(ellipse);
buttonGroup.add(rectangle);
buttonGroup.add(round);
buttonGroup.add(unselect);
shapePanel.add(createWeightPanel(
Messages.getString("Viz.ObjectShapePadding"), 0,
TMTopicNode.MAX_SHAPE_PADDING));
return shapePanel;
}
protected String promptForFile() {
JFileChooser dialog = new JFileChooser(lastIconPath);
dialog.setFileSelectionMode(JFileChooser.FILES_ONLY);
dialog.setAcceptAllFileFilterUsed(false);
dialog.setDialogTitle(Messages.getString("Viz.SelectIcon"));
dialog.setSelectedFile(new File(filenameField.getText()));
SimpleFileFilter filter = new SimpleFileFilter(Messages
.getString("Viz.ImageFiles"));
filter.addExtension("JPG");
filter.addExtension("JPEG");
filter.addExtension("GIF");
filter.addExtension("PNG");
dialog.setFileFilter(filter);
dialog.showOpenDialog(this);
File file = dialog.getSelectedFile();
if (file == null) return null;
lastIconPath = file.getPath();
return file.getAbsolutePath();
}
private void setAssociationTypeModel() {
model = new AssociationTypeConfigurationModel();
}
protected void setIconFilename(String string) {
if (typeList.getSelectedValue() == null)
return;
controller.setTypeIconFilename(selectedType, string);
}
public void setSelectedIconFilename(String string) {
filenameField.setText(string);
if (string == null || string.length() == 0)
clearButton.setEnabled(false);
else
clearButton.setEnabled(true);
}
protected void setWeight(int i) {
if (typeList.getSelectedValue() == null)
return;
model.setWeight(controller, selectedType, i);
}
public void setSelectedShape(int i) {
buttonGroup.setSelected(shapeMap[i].getModel(), true);
Enumeration elements = buttonGroup.getElements();
while(elements.hasMoreElements())
((AbstractButton)elements.nextElement()).repaint();
}
public void setSelectedFilter(int i) {
filterGroup.setSelected(filterMap[i].getModel(), true);
Enumeration elements = filterGroup.getElements();
while(elements.hasMoreElements())
((AbstractButton)elements.nextElement()).repaint();
}
/**
* When some other class changes the filter selection, this method updates
* this GUI.
* If other parts of the configuration, such as colour and shape,
* become changable in other classes, this method is probably the right place
* to update the GUI.
*/
public void updateSelectedFilter() {
int i = controller.getTypeVisibility(selectedType);
setSelectedFilter(i);
}
// Unselects all the radio topic/association type shape radio buttons.
private void unselectShapeRadioButtons() {
buttonGroup.setSelected(unselect.getModel(), true);
Enumeration elements = buttonGroup.getElements();
while(elements.hasMoreElements())
((AbstractButton)elements.nextElement()).repaint();
}
public void setSelectedWeight(int i) {
weight.setValue(i);
}
protected void setShape(int i) {
if (typeList.getSelectedValue() == null)
return;
model.setShape(controller, selectedType, i);
}
protected void setFilter(int i) {
if (typeList.getSelectedValue() == null)
return;
model.setFilter(controller, selectedType, i);
if (desktop != null)
desktop.configureFilterMenus();
}
private void setTopicTypeModel() {
model = new TopicTypeConfigurationModel();
}
public void valueChanged(ListSelectionEvent e) {
// Only handle the change in selection when the user has finally made his
// selection !
if (e.getValueIsAdjusting())
return;
TopicListItem selectedItem = (TopicListItem) typeList.getSelectedValue();
if (selectedItem == null) {
selectedType = null;
return;
}
selectedType = selectedItem.getTopic();
VizTopicMapConfigurationManager confMan = controller
.getConfigurationManager();
defaultColorSettingCheckbox.update();
// Make the colour chooser show the appropriate selected colour.
setChooserColor();
// Show the selected shape, or no selection when using default type settings
if (getUsingTopicModel() ?
confMan.getOccurrenceValue(selectedType,
confMan.getTopicTypeShapeTopic()) == null :
confMan.getOccurrenceValue(selectedType,
confMan.getAssociationTypeShapeTopic()) == null)
unselectShapeRadioButtons();
else
setSelectedShape(model.getShape(controller, selectedType));
// Show the filter selection.
setSelectedFilter(controller.getTypeVisibility(selectedType));
// Default selection is not applicable to default type.
if (getUsingTopicModel() ? selectedType == confMan.defaultType
: selectedType == confMan.defaultAssociationType)
filterDefault.setEnabled(false);
else
filterDefault.setEnabled(true);
// Default button is not applicable to default type.
defaultButton.setEnabled(!(selectedType == confMan.defaultType
|| selectedType == confMan.defaultAssociationType));
// WORKAROUND (HORRIBLE HACK): When the slider is updated, the underlying
// value is automatically changed. This corrupts the behavior of
// Default Type, which should apply to all types with no explicit setting.
// Hence the need to check if it was already set and then remove it after
// setSelectedWeight has changed it.
TopicIF paddingTopic = confMan.getTopicTypeShapePaddingTopic();
TopicIF configType = confMan.getConfigTopic(selectedType);
boolean hadShapePadding = confMan.getOccurrence(configType, paddingTopic)
!= null;
setSelectedWeight(model.getWeight(controller, selectedType));
if (!hadShapePadding)
confMan.removeOccurrence(configType, paddingTopic);
setSelectedIconFilename(controller.getTypeIconFilename(selectedType));
// Make the appropriate font selection (or no selection, as the case may be)
// in the font selection interface.
updateFontSelection();
}
/**
* Make the appropriate font selection (or no selection, as the case may be)
* in the font selection interface.
*/
private void updateFontSelection() {
VizTopicMapConfigurationManager confMan = controller
.getConfigurationManager();
String fontString = confMan.getOccurrenceValue(selectedType,
confMan.getTopicTypeFontTopic());
if (fontString == null)
unselectFont();
else {
Font font = confMan.parseFont(fontString);
setSelectedFont(font);
}
}
private void setChooserColor() {
// Needed by the config manager to avoid updating view with new color.
controller.setIgnoreStateChangedEvent(true);
Color c = model.getColor(controller, selectedType);
if (c != null)
chooser.setColor(c);
// Needed by the config manager to avoid updating view with new color.
controller.setIgnoreStateChangedEvent(false);
}
private void setSelectedFont(Font typeFont) {
// We need @ignoreSelection since we cannot set the current
// font without signalling the font changes callbacks
ignoreSelection = true;
fontList.setSelectedValue(typeFont.getFamily(), true);
sizeList.setSelectedValue(Integer.toString(typeFont.getSize()), true);
bold.setSelected(typeFont.isBold());
italic.setSelected(typeFont.isItalic());
ignoreSelection = false;
}
// Remove all font selection (glyph, size, ?bold and ?italics) from the font
// selection interface. This will typically happen for fonts that use default
// font settings.
private void unselectFont() {
// We need @ignoreSelection since we cannot set the current
// font without signalling the font changes callbacks
ignoreSelection = true;
int[] noInts = new int[0];
fontList.setSelectedIndices(noInts);
sizeList.setSelectedIndices(noInts);
bold.setSelected(false);
italic.setSelected(false);
ignoreSelection = false;
}
/**
* INTERNAL: Model object to represent what is being configured.
*/
private interface ConfigurationModelIF {
public void addAdditionalItems(Vector ttypes);
public void buildGeneralConfigPanel(TypesConfigFrame frame, JPanel config);
public int getWeight(VizController controller, TopicIF selectedType);
public Collection getListItems(VizController controller);
public int getShape(VizController controller, TopicIF selectedType);
public String getTitle();
public void setWeight(VizController controller, TopicIF selectedType,
int i);
public void setFilter(VizController controller, TopicIF selectedType, int i);
public void setShape(VizController controller, TopicIF selectedType, int i);
public Color getColor(VizController controller, TopicIF selectedType);
}
/**
* INTERNAL: PRIVATE: Description: Model object to represent TopicTypes
* Examples:
*/
private class AssociationTypeConfigurationModel implements
ConfigurationModelIF {
public void addAdditionalItems(Vector ttypes) {
// For association types do nothing
}
public void buildGeneralConfigPanel(TypesConfigFrame frame, JPanel config) {
frame.buildAssociationTypeGeneralConfigPanel(config);
}
public Color getColor(VizController controller, TopicIF selectedType) {
return controller.getAssociationTypeColor(selectedType);
}
public int getWeight(VizController controller, TopicIF selectedType) {
return controller.getAssoicationTypeLineWeight(selectedType);
}
public Collection getListItems(VizController controller) {
return controller.getAssociationTypes();
}
public int getShape(VizController controller, TopicIF selectedType) {
return controller.getAssoicationTypeShape(selectedType);
}
public String getTitle() {
return Messages.getString("Viz.AssociationTypeConfiguration");
}
public void setWeight(VizController controller, TopicIF selectedType,
int i) {
controller.setAssociationTypeLineWeight(selectedType, i);
}
public void setFilter(VizController controller, TopicIF selectedType,
int i) {
controller.setAssociationTypeVisibility(selectedType, i);
}
public void setShape(VizController controller, TopicIF selectedType,
int i) {
controller.setAssociationTypeShape(selectedType, i);
}
}
/**
* INTERNAL: PRIVATE: Description: Model object to represent TopicTypes
* Examples:
*/
private class TopicTypeConfigurationModel implements ConfigurationModelIF {
public void addAdditionalItems(Vector ttypes) {
ttypes.add(new TopicListItem(Messages.getString("Viz.Untyped")));
}
public void buildGeneralConfigPanel(TypesConfigFrame frame, JPanel config) {
frame.buildTopicTypeGeneralConfigPanel(config);
}
public Color getColor(VizController controller, TopicIF selectedType) {
return controller.getTopicTypeColor(selectedType);
}
public int getWeight(VizController controller, TopicIF selectedType) {
return controller.getTopicTypeShapePadding(selectedType);
}
public Collection getListItems(VizController controller) {
return controller.getAllTopicTypesWithNull();
}
public int getShape(VizController controller, TopicIF selectedType) {
return controller.getTopicTypeShape(selectedType);
}
public String getTitle() {
return Messages.getString("Viz.TopicTypeConfiguration");
}
public void setWeight(VizController controller, TopicIF selectedType,
int i) {
controller.setTopicTypeShapePadding(selectedType, i);
}
public void setFilter(VizController controller, TopicIF selectedType,
int i) {
controller.setTopicTypeVisibility(selectedType, i);
}
public void setShape(VizController controller, TopicIF selectedType,
int i) {
controller.setTopicTypeShape(selectedType, i);
}
}
}