/*
* TreeColouringController.java
*
* Copyright (C) 2006-2014 Andrew Rambaut
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package figtree.panel;
import jebl.evolution.trees.Tree;
import jebl.evolution.graphs.Node;
import figtree.treeviewer.TreeViewer;
import figtree.treeviewer.TreeViewerListener;
import figtree.treeviewer.decorators.*;
import jebl.util.Attributable;
import jam.controlpalettes.AbstractController;
import jam.panels.OptionsPanel;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.*;
/**
* @author Andrew Rambaut
* @version $Id$
*
* $HeadURL$
*
* $LastChangedBy$
* $LastChangedDate$
* $LastChangedRevision$
*/
public class TreeColouringController extends AbstractController {
private static final String CONTROLLER_KEY = "appearance";
private static final String BRANCH_COLOR_ATTRIBUTE_KEY = "branchColorAttribute";
public TreeColouringController(final TreeViewer treeViewer) {
this(treeViewer, "Colour by:");
}
public TreeColouringController(final TreeViewer treeViewer, String label) {
final AttributableDecorator branchDecorator = new AttributableDecorator();
branchDecorator.setPaintAttributeName("!color");
branchDecorator.setStrokeAttributeName("!stroke");
treeViewer.setBranchDecorator(branchDecorator, false);
optionsPanel = new OptionsPanel();
branchColourAttributeCombo = new JComboBox(new String[] { "No attributes" });
setupAttributes(treeViewer.getTrees());
branchColourAttributeCombo.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent itemEvent) {
Set<Node> nodes = new HashSet<Node>();
for (Tree tree : treeViewer.getTrees()) {
for (Node node : tree.getNodes()) {
nodes.add(node);
}
}
String attribute = (String) branchColourAttributeCombo.getSelectedItem();
if (attribute != null && attribute.length() > 0) {
if (attribute.endsWith("*")) {
Decorator decorator = new DiscreteColourDecorator();
treeViewer.setBranchColouringDecorator(attribute.substring(0, attribute.length() - 2), decorator);
treeViewer.setBranchDecorator(null, false);
} else if (DiscreteColourDecorator.isDiscrete(attribute, nodes)) {
Decorator decorator = new HSBDiscreteColourDecorator(attribute, nodes);
treeViewer.setBranchColouringDecorator(null, null);
treeViewer.setBranchDecorator(decorator, false);
} else {
Decorator decorator = new InterpolatingColourDecorator(
new ContinuousScale(attribute, nodes),
new Color(192, 16, 0), new Color(0, 16, 192));
treeViewer.setBranchColouringDecorator(null, null);
treeViewer.setBranchDecorator(decorator, false);
}
}
}
});
optionsPanel.addComponentWithLabel(label, branchColourAttributeCombo);
treeViewer.addTreeViewerListener(new TreeViewerListener() {
public void treeChanged() {
setupAttributes(treeViewer.getTrees());
optionsPanel.repaint();
}
public void treeSettingsChanged() {
// nothing to do
}
});
}
private void setupAttributes(Collection<? extends Tree> trees) {
Object selected = branchColourAttributeCombo.getSelectedItem();
branchColourAttributeCombo.removeAllItems();
//branchColourAttributeCombo.addItem("User Selection");
if (trees == null) {
return;
}
for (Tree tree : trees) {
for (String name : getAttributeNames(tree.getNodes())) {
branchColourAttributeCombo.addItem(name);
}
}
branchColourAttributeCombo.setSelectedItem(selected);
}
private String[] getAttributeNames(Collection<? extends Attributable> items) {
Set<String> attributeNames = new TreeSet<String>();
for (Attributable item : items) {
for (String name : item.getAttributeNames()) {
if (!name.startsWith("!")) {
Object attr = item.getAttribute(name);
if (!(attr instanceof Object[])) {
attributeNames.add(name);
} else {
boolean isColouring = true;
Object[] array = (Object[])attr;
boolean isIndex = true;
for (Object element : array) {
if (isIndex && !(element instanceof Integer) ||
!isIndex && !(element instanceof Double)) {
isColouring = false;
break;
}
isIndex = !isIndex;
}
if (isIndex) {
// a colouring should finish on an index (which means isIndex should be false)...
isColouring = false;
}
if (isColouring) {
attributeNames.add(name + " *");
}
}
}
}
}
String[] attributeNameArray = new String[attributeNames.size()];
attributeNames.toArray(attributeNameArray);
return attributeNameArray;
}
public JComponent getTitleComponent() {
return null;
}
public JPanel getPanel() {
return optionsPanel;
}
public boolean isInitiallyVisible() {
return false;
}
public void initialize() {
// nothing to do
}
public void setSettings(Map<String,Object> settings) {
branchColourAttributeCombo.setSelectedItem(settings.get(CONTROLLER_KEY+"."+BRANCH_COLOR_ATTRIBUTE_KEY));
}
public void getSettings(Map<String, Object> settings) {
if (branchColourAttributeCombo.getSelectedItem() != null) {
settings.put(CONTROLLER_KEY + "." + BRANCH_COLOR_ATTRIBUTE_KEY, branchColourAttributeCombo.getSelectedItem().toString());
} else {
settings.put(CONTROLLER_KEY + "." + BRANCH_COLOR_ATTRIBUTE_KEY, "none");
}
}
private final OptionsPanel optionsPanel;
private final JComboBox branchColourAttributeCombo;
}