Java tutorial
/* * Copyright 2004-2010 Institute of Software Technology and Interactive Systems, Vienna University of Technology * * 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.ifs.tuwien.ac.at/dm/somtoolbox/license.html * * 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 at.tuwien.ifs.somtoolbox.apps.viewer.controls; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.awt.Paint; import java.awt.Rectangle; import java.awt.Shape; import java.awt.Stroke; import java.util.logging.Logger; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import org.apache.commons.collections15.Transformer; import edu.uci.ics.jung.algorithms.layout.Layout; import edu.uci.ics.jung.algorithms.layout.TreeLayout; import edu.uci.ics.jung.graph.DelegateTree; import edu.uci.ics.jung.graph.Graph; import edu.uci.ics.jung.graph.util.Context; import edu.uci.ics.jung.visualization.RenderContext; import edu.uci.ics.jung.visualization.VisualizationViewer; import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse; import edu.uci.ics.jung.visualization.control.ModalGraphMouse; import at.tuwien.ifs.somtoolbox.util.UiUtils; import at.tuwien.ifs.somtoolbox.visualization.Palette; import at.tuwien.ifs.somtoolbox.visualization.Palettes; import at.tuwien.ifs.somtoolbox.visualization.clustering.ClusterNode; import at.tuwien.ifs.somtoolbox.visualization.clustering.ClusteringTree; /** * @author tomas * @version $Id: $ */ public class DendogramView { private static final Logger log = Logger.getLogger(DendogramView.class.getName()); protected Palette palette = Palettes.getPaletteByName(getPreferredPaletteName()); private static final float MAX_STROKE_WIDTH = 1; private static final float DEFAULT_STROKE_WIDTH = 0.1f; private JFrame frame; private JLabel lblNewLabel; private int nodeId = 0; private Double mMergeCostMax = null; private Double mMergeCostMin = null; private Double mMergeCostSumMax = null; private Double mMergeCostSumMin = null; private JSpinner mMainSpinnerCluster = null; private JSpinner spinnerCluster; private JPanel clusterPanel; private int maxCluster = 0; /** * Create the application. */ public DendogramView() { initialize(); } /** * Create the application. */ public DendogramView(int maxCluster, JSpinner _cs) { initialize(); this.maxCluster = maxCluster; this.mMainSpinnerCluster = _cs; } /** * Initialize the contents of the frame. */ private void initialize() { frame = new JFrame(); frame.setBounds(100, 100, 578, 414); frame.setAlwaysOnTop(true); frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); } /** * @param t * @param numClusters2 */ public void update(ClusteringTree t, int numClusters) { frame.setVisible(true); frame.getContentPane().removeAll(); try { // create spinner-panel clusterPanel = UiUtils.makeBorderedPanel(new FlowLayout(FlowLayout.LEFT, 10, 0), "Clusters"); spinnerCluster = new JSpinner(new SpinnerNumberModel(1, 1, maxCluster, 1)); spinnerCluster.setValue(numClusters); spinnerCluster.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { if (mMainSpinnerCluster != null) { mMainSpinnerCluster.setValue(((JSpinner) e.getSource()).getValue()); } } }); UiUtils.fillPanel(clusterPanel, new JLabel("#"), spinnerCluster); frame.getContentPane().add(clusterPanel, BorderLayout.NORTH); // create graph VisualizationViewer g = generateGraph(t, numClusters); frame.getContentPane().add(g, BorderLayout.CENTER); frame.setSize(frame.getWidth() + 1, frame.getHeight() + 1); frame.setSize(frame.getWidth() - 1, frame.getHeight() - 1); } catch (Exception e) { e.printStackTrace(); } } /** * @param t * @param numClusters * @return */ private VisualizationViewer generateGraph(ClusteringTree t, final int numClusters) { DelegateTree<ChildDG, EdgeDG> g = new DelegateTree<ChildDG, EdgeDG>(); ClusterNode root = t.findNode(1); mMergeCostMax = null; mMergeCostMin = null; mMergeCostSumMax = null; mMergeCostSumMin = null; calcMergeCostSum(root, root.getMergeCost(), numClusters); findMinMaxMergeCost(root, true, numClusters); nodeId = 0; ChildDG rc = new ChildDG(root); addChildren(root, g, rc, numClusters); Layout<ChildDG, EdgeDG> layout = new TreeLayout<ChildDG, EdgeDG>(g); VisualizationViewer<ChildDG, EdgeDG> graphComponent = new VisualizationViewer<ChildDG, EdgeDG>(layout); DefaultModalGraphMouse gm = new DefaultModalGraphMouse(); gm.setMode(ModalGraphMouse.Mode.TRANSFORMING); graphComponent.setGraphMouse(gm); graphComponent.enableInputMethods(true); RenderContext<ChildDG, EdgeDG> c = graphComponent.getRenderContext(); graphComponent.setVertexToolTipTransformer(new Transformer<ChildDG, String>() { @Override public String transform(ChildDG c) { if (c.getNode().getMergeCost() == null) { return "count:" + c.getNode().getNodes().length + " " + c.getTooltip(); } else { return "merge cotst:" + c.getNode().getMergeCost() + " count:" + c.getNode().getNodes().length + " " + c.getTooltip(); } } }); graphComponent.setSize(frame.getContentPane().getWidth(), frame.getContentPane().getHeight() - clusterPanel.getHeight()); // change edge-stroke-thickness c.setEdgeStrokeTransformer(new Transformer<EdgeDG, Stroke>() { @Override public Stroke transform(EdgeDG _arg0) { return new BasicStroke(_arg0.getMergeCost().floatValue() * MAX_STROKE_WIDTH); } }); final Rectangle fake = new Rectangle(1, 1); c.setEdgeArrowTransformer(new Transformer<Context<Graph<ChildDG, EdgeDG>, EdgeDG>, Shape>() { @Override public Shape transform(Context<Graph<ChildDG, EdgeDG>, EdgeDG> _arg0) { return fake; } }); // change vertex-fill-color c.setVertexFillPaintTransformer(new Transformer<ChildDG, Paint>() { @Override public Paint transform(ChildDG _arg0) { if (_arg0.getPaint() == null) { if (_arg0.getMergeCostSum() != null) { double normalized = getNormalizedValue(_arg0.getMergeCostSum(), mMergeCostSumMax, mMergeCostSumMin, _arg0.getMergeCostSum()); int cc = (int) Math.round(normalized * (palette.getColors().length - 1)); return palette.getColor(cc); } else { return palette.getColor(palette.getColors().length - 1); } } else { return _arg0.getPaint(); } } }); return graphComponent; } /** * @param root * @param g * @param numClusters * @param parrent */ private void addChildren(ClusterNode n, DelegateTree<ChildDG, EdgeDG> g, ChildDG parent, int numClusters) { nodeId++; if (g.getVertexCount() == 0) { g.setRoot(parent); if (n.getLevel() < numClusters) { if (n.getChild1() != null) { addChildren(n.getChild1(), g, parent, numClusters); } if (n.getChild2() != null) { addChildren(n.getChild2(), g, parent, numClusters); } } return; } ChildDG child = new ChildDG(n); double mergecost = n.getMergeCost() != null ? n.getMergeCost() : 1.0; g.addChild( new EdgeDG(nodeId, getNormalizedValue(mergecost, mMergeCostMax, mMergeCostMin, DEFAULT_STROKE_WIDTH)), parent, child); if (n.getLevel() < numClusters) { if (n.getChild1() != null) { addChildren(n.getChild1(), g, child, numClusters); } if (n.getChild2() != null) { addChildren(n.getChild2(), g, child, numClusters); } } } private void findMinMaxMergeCost(ClusterNode root, boolean isRoot, int numClusters) { if (root != null) { Double m = root.getMergeCost(); Double mSum = root.getMergeCostSum(); if (m != null) { if (!isRoot) { if (mSum != null) { if (mMergeCostSumMin != null) { mMergeCostSumMax = mMergeCostSumMax == null || mSum > mMergeCostSumMax ? mSum : mMergeCostSumMax; } mMergeCostSumMin = mMergeCostSumMin == null || mSum < mMergeCostSumMin ? mSum : mMergeCostSumMin; } mMergeCostMax = mMergeCostMax == null || m > mMergeCostMax ? m : mMergeCostMax; mMergeCostMin = mMergeCostMin == null || m < mMergeCostMin ? m : mMergeCostMin; } findMinMaxMergeCost(root.getChild1(), false, numClusters); findMinMaxMergeCost(root.getChild2(), false, numClusters); } } } private Double getNormalizedValue(double value, Double max, Double min, double default_val) { if (max != null) { return (value - min) / (max - min); } return default_val; } private void calcMergeCostSum(ClusterNode root, Double mergeCostParent, int numClusters) { if (root != null && mergeCostParent != null) { ClusterNode c1 = root.getChild1(); if (c1 != null) { if (c1.getMergeCost() != null) { c1.setMergeCostSum(mergeCostParent + c1.getMergeCost()); } else { c1.setMergeCostSum(mergeCostParent); } if (c1.getLevel() <= numClusters) { calcMergeCostSum(c1, c1.getMergeCostSum(), numClusters); } } ClusterNode c2 = root.getChild2(); if (c2 != null) { if (c2.getMergeCost() != null) { c2.setMergeCostSum(mergeCostParent + c2.getMergeCost()); } else { c2.setMergeCostSum(mergeCostParent); } if (c2.getLevel() <= numClusters) { calcMergeCostSum(c2, c2.getMergeCostSum(), numClusters); } } } } public String getPreferredPaletteName() { return Palettes.getDefaultPalette().getName(); } }