/* * TreeAppearanceController.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.treeviewer; import figtree.treeviewer.painters.AttributeComboHelper; import figtree.treeviewer.painters.AttributeComboHelperListener; import figtree.treeviewer.painters.NodeShapePainter; import jam.controlpalettes.ControllerListener; import jam.controlpalettes.AbstractController; import jam.panels.OptionsPanel; import javax.swing.*; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.*; import java.awt.event.*; import java.util.*; import java.util.prefs.Preferences; import figtree.treeviewer.decorators.*; import jebl.evolution.trees.RootedTree; /** * @author Andrew Rambaut * @version $Id$ * * $HeadURL$ * * $LastChangedBy$ * $LastChangedDate$ * $LastChangedRevision$ */ public class TreeAppearanceController extends AbstractController { private static final String CONTROLLER_TITLE = "Appearance"; public static Preferences PREFS = Preferences.userNodeForPackage(TreeViewer.class); public static final String CONTROLLER_KEY = "appearance"; public static final String FOREGROUND_COLOUR_KEY = "foregroundColour"; public static final String BACKGROUND_COLOUR_KEY = "backgroundColour"; public static final String SELECTION_COLOUR_KEY = "selectionColour"; public static final String BRANCH_COLOR_ATTRIBUTE_KEY = "branchColorAttribute"; public static final String BRANCH_COLOR_GRADIENT_KEY = "branchColorGradient"; public static final String HILIGHTING_GRADIENT_KEY = "hilightingGradient"; public static final String BACKGROUND_COLOR_ATTRIBUTE_KEY = "backgroundColorAttribute"; public static final String BRANCH_LINE_WIDTH_KEY = "branchLineWidth"; public static final String BRANCH_MIN_LINE_WIDTH_KEY = "branchMinLineWidth"; public static final String BRANCH_WIDTH_ATTRIBUTE_KEY = "branchWidthAttribute"; // The defaults if there is nothing in the preferences public static Color DEFAULT_FOREGROUND_COLOUR = Color.BLACK; public static Color DEFAULT_BACKGROUND_COLOUR = Color.WHITE; public static Color DEFAULT_SELECTION_COLOUR = new Color(45, 54, 128); public static float DEFAULT_BRANCH_LINE_WIDTH = 1.0f; public static final String FIXED = "Fixed"; public TreeAppearanceController(final TreeViewer treeViewer, final JFrame frame, final AttributeColourController colourController) { this.treeViewer = treeViewer; this.colourController = colourController; userBranchColourDecorator = new AttributableDecorator(); userBranchColourDecorator.setPaintAttributeName("!color"); userBranchColourDecorator.setStrokeAttributeName("!stroke"); treeViewer.setBranchDecorator(userBranchColourDecorator, false); int foregroundRGB = TreeAppearanceController.PREFS.getInt(CONTROLLER_KEY + "." + FOREGROUND_COLOUR_KEY, DEFAULT_FOREGROUND_COLOUR.getRGB()); int backgroundRGB = TreeAppearanceController.PREFS.getInt(CONTROLLER_KEY + "." + BACKGROUND_COLOUR_KEY, DEFAULT_BACKGROUND_COLOUR.getRGB()); int selectionRGB = TreeAppearanceController.PREFS.getInt(CONTROLLER_KEY + "." + SELECTION_COLOUR_KEY, DEFAULT_SELECTION_COLOUR.getRGB()); float branchLineWidth = TreeAppearanceController.PREFS.getFloat(CONTROLLER_KEY + "." + BRANCH_LINE_WIDTH_KEY, DEFAULT_BRANCH_LINE_WIDTH); treeViewer.setForeground(new Color(foregroundRGB)); treeViewer.setBackground(new Color(backgroundRGB)); treeViewer.setSelectionColor(new Color(selectionRGB)); treeViewer.setBranchStroke(new BasicStroke(branchLineWidth, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); titleLabel = new JLabel(CONTROLLER_TITLE); optionsPanel = new ControllerOptionsPanel(2, 0); branchWidthAttributeCombo = new JComboBox(new String[] { "No attributes" }); branchColourAttributeCombo = new JComboBox(new String[] { "No attributes" }); backgroundColourAttributeCombo = new JComboBox(new String[] { "No attributes" }); // setupAttributes(treeViewer.getTrees()); // branchColourSettings.autoRange = true; // branchColourSettings.fromValue = 0.0; // branchColourSettings.toValue = 1.0; // branchColourSettings.fromColour = new Color(0, 16, 192); // branchColourSettings.toColour = new Color(192, 16, 0); // branchColourSettings.middleColour = new Color(0, 0, 0); branchColourIsGradient = TreeAppearanceController.PREFS.getBoolean(CONTROLLER_KEY + "." + BRANCH_COLOR_GRADIENT_KEY, false); final JButton setupColourButton = new JButton("Colours"); colourController.setupControls(branchColourAttributeCombo, setupColourButton); colourController.addControllerListener(new ControllerListener() { @Override public void controlsChanged() { setupBranchDecorators(); } }); branchColourGradientCheck = new JCheckBox("Gradient"); branchColourGradientCheck.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent changeEvent) { branchColourIsGradient = branchColourGradientCheck.isSelected(); setupBranchDecorators(); } }); optionsPanel.addComponentWithLabel("Colour by:", branchColourAttributeCombo); final JLabel setupColourButtonLabel = optionsPanel.addComponentWithLabel("Setup:", setupColourButton); optionsPanel.addComponent(branchColourGradientCheck); optionsPanel.addSeparator(); boolean hilightingGradient = TreeAppearanceController.PREFS.getBoolean(CONTROLLER_KEY + "." + HILIGHTING_GRADIENT_KEY, false); hilightingGradientCheck = new JCheckBox("Hilight with gradient"); hilightingGradientCheck.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent changeEvent) { treeViewer.setHilightingGradient(hilightingGradientCheck.isSelected()); } }); optionsPanel.addComponent(hilightingGradientCheck); hilightingGradientCheck.setSelected(hilightingGradient); optionsPanel.addSeparator(); branchLineWidthSpinner = new JSpinner(new SpinnerNumberModel(1.0, 0.01, 48.0, 1.0)); optionsPanel.addComponentWithLabel("Line Weight:", branchLineWidthSpinner); optionsPanel.addComponentWithLabel("Width by:", branchWidthAttributeCombo); branchMinLineWidthSpinner = new JSpinner(new SpinnerNumberModel(0.0, 0.0, 48.0, 1.0)); final JLabel label = optionsPanel.addComponentWithLabel("Min Weight:", branchMinLineWidthSpinner); optionsPanel.addSeparator(); // backgroundColourSettings.autoRange = true; // backgroundColourSettings.fromValue = 0.0; // backgroundColourSettings.toValue = 1.0; // backgroundColourSettings.fromColour = new Color(255, 255, 255); // backgroundColourSettings.toColour = new Color(192, 16, 0); // backgroundColourSettings.middleColour = null; final JButton bgSetupColourButton = new JButton("Colours"); colourController.setupControls(backgroundColourAttributeCombo, bgSetupColourButton); colourController.addControllerListener(new ControllerListener() { @Override public void controlsChanged() { setupBranchDecorators(); } }); optionsPanel.addComponentWithLabel("Background:", backgroundColourAttributeCombo); final JLabel bgSetupColourButtonLabel = optionsPanel.addComponentWithLabel("Setup:", bgSetupColourButton); new AttributeComboHelper(branchColourAttributeCombo, treeViewer, "User selection", false, true).addListener(new AttributeComboHelperListener() { @Override public void attributeComboChanged() { boolean isSelected = branchColourAttributeCombo.getSelectedIndex() != 0; setupColourButtonLabel.setEnabled(isSelected); setupColourButton.setEnabled(isSelected); setupBranchDecorators(); } }); new AttributeComboHelper(backgroundColourAttributeCombo, treeViewer, "Default").addListener(new AttributeComboHelperListener() { @Override public void attributeComboChanged() { boolean isSelected = backgroundColourAttributeCombo.getSelectedIndex() != 0; bgSetupColourButtonLabel.setEnabled(isSelected); bgSetupColourButton.setEnabled(isSelected); setupBranchDecorators(); } }); new AttributeComboHelper(branchWidthAttributeCombo, treeViewer, FIXED, true, false).addListener(new AttributeComboHelperListener() { @Override public void attributeComboChanged() { boolean isSelected = branchColourAttributeCombo.getSelectedIndex() != 0; label.setEnabled(isSelected); branchMinLineWidthSpinner.setEnabled(isSelected); setupBranchDecorators(); } }); branchLineWidthSpinner.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent changeEvent) { float lineWidth = ((Double) branchLineWidthSpinner.getValue()).floatValue(); treeViewer.setBranchStroke(new BasicStroke(lineWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER)); setupBranchDecorators(); } }); branchMinLineWidthSpinner.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent changeEvent) { setupBranchDecorators(); } }); } private void setupBranchDecorators() { Decorator colourDecorator = colourController.getColourDecorator(branchColourAttributeCombo, userBranchColourDecorator); // DiversityContinuousColourDecorator colourDecorator = new DiversityContinuousColourDecorator(); // colourDecorator.setTree((RootedTree)treeViewer.getCurrentTree()); // if (colourDecorator == null) { // if (attribute.endsWith("*")) { // // This is a branch colouring (i.e., the colour can change // // along the length of the branch... // treeViewer.setBranchColouringDecorator( // attribute.substring(0, attribute.length() - 2), // new DiscreteColourDecorator()); // return; // if (colourDecorator != null && colourDecorator.isGradient()) { // // At present using a gradient precludes the use of the compoundDecorator // // and thus the branch width.. // treeViewer.setBranchDecorator(colourDecorator); // return; // } CompoundDecorator compoundDecorator = new CompoundDecorator(); if (colourDecorator != null) { treeViewer.setBranchColouringDecorator(null, null); compoundDecorator.addDecorator(colourDecorator); } if (branchWidthAttributeCombo.getSelectedIndex() > 0) { String attribute = (String) branchWidthAttributeCombo.getSelectedItem(); ContinuousScale widthScale = new ContinuousScale(attribute, treeViewer.getTrees().get(0).getNodes()); double fromWidth = (Double) branchMinLineWidthSpinner.getValue(); double toWidth = (Double)branchLineWidthSpinner.getValue() + fromWidth; compoundDecorator.addDecorator(new ContinuousStrokeDecorator( widthScale, (float)fromWidth, (float)toWidth) ); } treeViewer.setBranchDecorator(compoundDecorator, branchColourIsGradient); Decorator backgroundDecorator = null; if (backgroundColourAttributeCombo.getSelectedIndex() > 1) { backgroundDecorator = colourController.getColourDecorator(backgroundColourAttributeCombo, null); } treeViewer.setNodeBackgroundDecorator(backgroundDecorator); } public JComponent getTitleComponent() { return titleLabel; } public JPanel getPanel() { return optionsPanel; } public boolean isInitiallyVisible() { return false; } public void initialize() { // nothing to do } public void setSettings(Map<String, Object> settings) { // These settings don't have controls yet but they will! treeViewer.setForeground((Color)settings.get(CONTROLLER_KEY + "." + FOREGROUND_COLOUR_KEY)); treeViewer.setBackground((Color)settings.get(CONTROLLER_KEY + "." + BACKGROUND_COLOUR_KEY)); treeViewer.setSelectionColor((Color)settings.get(CONTROLLER_KEY + "." + SELECTION_COLOUR_KEY)); branchColourAttributeCombo.setSelectedItem(settings.get(CONTROLLER_KEY+"."+BRANCH_COLOR_ATTRIBUTE_KEY)); branchColourGradientCheck.setSelected((Boolean)settings.get(CONTROLLER_KEY+"."+BRANCH_COLOR_GRADIENT_KEY)); hilightingGradientCheck.setSelected((Boolean)settings.get(CONTROLLER_KEY+"."+HILIGHTING_GRADIENT_KEY)); backgroundColourAttributeCombo.setSelectedItem(settings.get(CONTROLLER_KEY + "." + BACKGROUND_COLOR_ATTRIBUTE_KEY)); branchLineWidthSpinner.setValue((Double) settings.get(CONTROLLER_KEY + "." + BRANCH_LINE_WIDTH_KEY)); branchWidthAttributeCombo.setSelectedItem(settings.get(CONTROLLER_KEY+"."+BRANCH_WIDTH_ATTRIBUTE_KEY)); branchMinLineWidthSpinner.setValue((Double) settings.get(CONTROLLER_KEY + "." + BRANCH_MIN_LINE_WIDTH_KEY)); } public void getSettings(Map<String, Object> settings) { // These settings don't have controls yet but they will! settings.put(CONTROLLER_KEY + "." + FOREGROUND_COLOUR_KEY, treeViewer.getForeground()); settings.put(CONTROLLER_KEY + "." + BACKGROUND_COLOUR_KEY, treeViewer.getBackground()); settings.put(CONTROLLER_KEY + "." + SELECTION_COLOUR_KEY, treeViewer.getSelectionPaint()); settings.put(CONTROLLER_KEY + "." + BRANCH_COLOR_ATTRIBUTE_KEY, branchColourAttributeCombo.getSelectedItem().toString()); settings.put(CONTROLLER_KEY + "." + BRANCH_COLOR_GRADIENT_KEY, branchColourGradientCheck.isSelected()); settings.put(CONTROLLER_KEY + "." + HILIGHTING_GRADIENT_KEY, hilightingGradientCheck.isSelected()); settings.put(CONTROLLER_KEY + "." + BACKGROUND_COLOR_ATTRIBUTE_KEY, backgroundColourAttributeCombo.getSelectedItem().toString()); settings.put(CONTROLLER_KEY + "." + BRANCH_LINE_WIDTH_KEY, branchLineWidthSpinner.getValue()); settings.put(CONTROLLER_KEY + "." + BRANCH_WIDTH_ATTRIBUTE_KEY, branchWidthAttributeCombo.getSelectedItem().toString()); settings.put(CONTROLLER_KEY + "." + BRANCH_MIN_LINE_WIDTH_KEY, branchMinLineWidthSpinner.getValue()); } private final AttributeColourController colourController; private final AttributableDecorator userBranchColourDecorator; private final JLabel titleLabel; private final OptionsPanel optionsPanel; private final JComboBox branchColourAttributeCombo; private final JCheckBox branchColourGradientCheck; private final JCheckBox hilightingGradientCheck; private final JComboBox backgroundColourAttributeCombo; private final JSpinner branchLineWidthSpinner; private final JSpinner branchMinLineWidthSpinner; private final JComboBox branchWidthAttributeCombo; private final TreeViewer treeViewer; private boolean branchColourIsGradient = false; }