[Swift-commit] r6668 - in trunk/src/org/griphyn/vdl/karajan/monitor: items monitors/swing

hategan at ci.uchicago.edu hategan at ci.uchicago.edu
Thu Jul 25 18:34:55 CDT 2013


Author: hategan
Date: 2013-07-25 18:34:55 -0500 (Thu, 25 Jul 2013)
New Revision: 6668

Modified:
   trunk/src/org/griphyn/vdl/karajan/monitor/items/SummaryItem.java
   trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GraphPanel.java
   trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GraphsPanel.java
   trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GridView.java
Log:
now with customizable dividers and layout persistence

Modified: trunk/src/org/griphyn/vdl/karajan/monitor/items/SummaryItem.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/monitor/items/SummaryItem.java	2013-07-25 20:01:31 UTC (rev 6667)
+++ trunk/src/org/griphyn/vdl/karajan/monitor/items/SummaryItem.java	2013-07-25 23:34:55 UTC (rev 6668)
@@ -63,6 +63,15 @@
     
     public static final State[] STATES = State.values();
     
+    public static State getStateByKey(String key) {
+        for (State s : STATES) {
+            if (s.getName().equals(key)) {
+                return s;
+            }
+        }
+        return null;
+    }
+    
 	private Map<String, Integer> counts;
 	private int status;
 	

Modified: trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GraphPanel.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GraphPanel.java	2013-07-25 20:01:31 UTC (rev 6667)
+++ trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GraphPanel.java	2013-07-25 23:34:55 UTC (rev 6668)
@@ -11,6 +11,7 @@
 
 import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Component;
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -18,6 +19,7 @@
 import java.util.Date;
 import java.util.List;
 import java.util.TimerTask;
+import java.util.prefs.Preferences;
 
 import javax.swing.JButton;
 import javax.swing.JColorChooser;
@@ -43,13 +45,15 @@
 
 public class GraphPanel extends JPanel {
     private SystemState state;
-    private JFreeChart states;
+    private JFreeChart chart;
     private final List<SummaryItem.State> enabled;
     private TimeSeriesCollection col;
     private JPanel legend;
+    private GraphsPanel gp;
 
-    public GraphPanel(SystemState state) {
+    public GraphPanel(SystemState state, GraphsPanel gp) {
         this.state = state;
+        this.gp = gp;
         this.setLayout(new BorderLayout());
         enabled = new ArrayList<SummaryItem.State>();
         createChart();
@@ -67,9 +71,9 @@
             TimeSeries ts = new TimeSeries(s.getName());
             col.addSeries(ts);
         }
-        states = ChartFactory.createTimeSeriesChart(null, "Time", "Count", col, false, true, false);
-        ChartPanel cp = new ChartPanel(states);
-        XYPlot plot = (XYPlot) states.getPlot();
+        chart = ChartFactory.createTimeSeriesChart(null, "Time", "Count", col, false, true, false);
+        ChartPanel cp = new ChartPanel(chart);
+        XYPlot plot = (XYPlot) chart.getPlot();
         plot.setBackgroundPaint(UIManager.getColor("TextField.background"));
         NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
         rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
@@ -89,7 +93,7 @@
     private void rebuildLegend() {
         legend.removeAll();
         for (int i = 0; i < enabled.size(); i++) {
-            makeLegendEntry(legend, states, enabled.get(i).getShortName(), i);
+            makeLegendEntry(legend, chart, enabled.get(i).getShortName(), i);
         }
         legend.add(new JLabel());
         legend.add(new JLabel());
@@ -102,7 +106,7 @@
             } 
         });
         
-        legend.add(newb);              
+        legend.add(newb);         
     }
 
     protected void displayAddPopup(JButton src) {
@@ -143,6 +147,7 @@
         col.removeSeries(series);
         rebuildLegend();
         repaint();
+        gp.saveLayout();
     }
     
     protected void displaySeriesPopup(final JFreeChart chart, final String label, final int series, final ColorButton button) {
@@ -173,7 +178,22 @@
         Color newColor = JColorChooser.showDialog(this, "Pick a color for " + label, color);
         button.setColor(newColor);
         ((XYPlot) chart.getPlot()).getRenderer().setSeriesPaint(series, newColor);
+        gp.saveLayout();
     }
+    
+    public void setColor(State s, Color color) {
+        int series = enabled.indexOf(s);
+        ((XYPlot) chart.getPlot()).getRenderer().setSeriesPaint(series, color);
+        int i = 0;
+        for (Component c : legend.getComponents()) {
+            if (c instanceof JButton) {
+                i++;
+                if (i == series + 1) {
+                    ((ColorButton) c).setColor(color);
+                }
+            }
+        }
+    }
 
     private void update() {
         SummaryItem summary = (SummaryItem) state.getItemByID(SummaryItem.ID, StatefulItemClass.WORKFLOW);
@@ -185,12 +205,50 @@
             ts.add(new Second(new Date()), summary.getCount(s));
         }
     }
+    
+    public void enable(State s) {
+        enable(s, true);
+    }
 
-    public void enable(State s) {
+    public void enable(State s, boolean save) {
         TimeSeries ts = new TimeSeries(s.getName());
         col.addSeries(ts);
         enabled.add(s);
         rebuildLegend();
         repaint();
+        if (save) {
+            gp.saveLayout();
+        }
     }
+
+    public void store(Preferences p) {
+        p.putInt("enabledCount", enabled.size());
+        for (int i = 0; i < enabled.size(); i++) {
+            Preferences gp = p.node("series" + i);
+            gp.put("key", enabled.get(i).getName());
+            Color color = (Color) chart.getPlot().getLegendItems().get(i).getLinePaint();
+            gp.putInt("color.r", color.getRed());
+            gp.putInt("color.g", color.getGreen());
+            gp.putInt("color.b", color.getBlue());
+        }
+    }
+    
+    public static GraphPanel load(Preferences p, SystemState state, GraphsPanel gps) {
+        GraphPanel g = new GraphPanel(state, gps);
+        int ec = p.getInt("enabledCount", 0);
+        for (int i = 0; i < ec; i++) {
+            Preferences gp = p.node("series" + i);
+            String key = gp.get("key", null);
+            if (key == null) {
+                throw new RuntimeException("Null series key");
+            }
+            int cr = gp.getInt("color.r", 255);
+            int cg = gp.getInt("color.g", 0);
+            int cb = gp.getInt("color.b", 0);
+            SummaryItem.State s = SummaryItem.getStateByKey(key);
+            g.enable(s, false);
+            g.setColor(s, new Color(cr, cg, cb));
+        }
+        return g;
+    }
 }

Modified: trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GraphsPanel.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GraphsPanel.java	2013-07-25 20:01:31 UTC (rev 6667)
+++ trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GraphsPanel.java	2013-07-25 23:34:55 UTC (rev 6668)
@@ -15,8 +15,8 @@
 import java.awt.event.ActionListener;
 import java.awt.image.BufferedImage;
 import java.net.URL;
-import java.util.Deque;
 import java.util.LinkedList;
+import java.util.prefs.Preferences;
 
 import javax.imageio.ImageIO;
 import javax.swing.ImageIcon;
@@ -78,15 +78,14 @@
     
     private SystemState state;
     
-    private int rows, columns;
     private JPanel toolBar;
     private JPopupMenu layoutPopup;
-    private Deque<JComponent> graphs;
+    private LinkedList<GraphPanel> graphs;
     private GridView grid;
     
     public GraphsPanel(SystemState state) {
         this.state = state;
-        this.graphs = new LinkedList<JComponent>();
+        this.graphs = new LinkedList<GraphPanel>();
         setLayout(new BorderLayout());
 
         toolBar = new JPanel();
@@ -108,12 +107,7 @@
         grid = new GridView();
         add(grid, BorderLayout.CENTER);
         
-        GraphPanel gp = new GraphPanel(state);
-        gp.enable(SummaryItem.State.ACTIVE);
-        gp.enable(SummaryItem.State.STAGE_IN);
-        gp.enable(SummaryItem.State.STAGE_OUT);
-        graphs.add(gp);
-        grid.add(gp);
+        loadLayout();
     }
 
     private void makeLayoutPopup() {
@@ -147,7 +141,7 @@
         grid.setLayout(t.copy());
         int count = grid.getCellCount();
         while (count > graphs.size()) {
-            GraphPanel gp = new GraphPanel(state);
+            GraphPanel gp = new GraphPanel(state, this);
             graphs.add(gp);
             grid.add(gp);
         }
@@ -155,8 +149,69 @@
             JComponent gp = graphs.removeLast();
             grid.remove(gp);
         }
+        
+        saveLayout();
     }
 
+    void saveLayout() {
+        /*
+         * Stored are:
+         * - the layout itself
+         * - the graph count and what's being graphed in each
+         * - the graph colors
+         */
+        try {
+            Preferences prefs = Preferences.userNodeForPackage(GraphsPanel.class);
+            Preferences layout = prefs.node("layout");
+            grid.getTree().store(layout);
+            prefs.putInt("graphCount", graphs.size());
+            for (int i = 0; i < graphs.size(); i++) {
+                Preferences gp = prefs.node("graph" + i);
+                graphs.get(i).store(gp);
+            }
+        }
+        catch (Exception e) {
+            System.err.println("Failed to save layout: "  + e);
+        }
+    }
+    
+    private void loadLayout() {
+        grid.clear();
+        graphs.clear();
+        try {
+            Preferences prefs = Preferences.userNodeForPackage(GraphsPanel.class);
+            if (prefs.nodeExists("layout")) {
+                grid.setLayout(GridView.Tree.load(prefs.node("layout")));
+                int gc = prefs.getInt("graphCount", 0);
+                for (int i = 0; i < gc; i++) {
+                    GraphPanel gp = GraphPanel.load(prefs.node("graph" + i), state, this);
+                    graphs.add(gp);
+                    grid.add(gp);
+                }
+            }
+            else {
+                setDefaultLayout();
+            }
+        }
+        catch (Exception e) {
+            System.err.println("Failed to load layout: "  + e + ". Using default.");
+            setDefaultLayout();
+        }
+    }
+    
+    private void setDefaultLayout() {
+        grid.clear();
+        graphs.clear();
+        grid.setLayout(new Tree());
+        GraphPanel gp = new GraphPanel(state, this);
+        gp.enable(SummaryItem.State.ACTIVE);
+        gp.enable(SummaryItem.State.STAGE_IN);
+        gp.enable(SummaryItem.State.STAGE_OUT);
+        graphs.add(gp);
+        grid.add(gp);
+        saveLayout();
+    }
+
     protected void displayLayoutPopup(JButton src) {
         layoutPopup.show(src, 6, 6);
     }

Modified: trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GridView.java
===================================================================
--- trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GridView.java	2013-07-25 20:01:31 UTC (rev 6667)
+++ trunk/src/org/griphyn/vdl/karajan/monitor/monitors/swing/GridView.java	2013-07-25 23:34:55 UTC (rev 6668)
@@ -11,41 +11,84 @@
 
 import java.awt.BasicStroke;
 import java.awt.Component;
+import java.awt.Cursor;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.Stroke;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.prefs.BackingStoreException;
+import java.util.prefs.Preferences;
 
 import javax.swing.ImageIcon;
+import javax.swing.JComponent;
 import javax.swing.JPanel;
 import javax.swing.UIManager;
 
 public class GridView extends JPanel {
     public static final int DIVIDER_SIZE = 10;
 
+    public static final Cursor H_RESIZE_CURSOR = Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR);
+    public static final Cursor V_RESIZE_CURSOR = Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR);
     
-    private GridView.Tree tree;
+    public static final Stroke DIVIDER_STROKE = new BasicStroke(1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND, 0, 
+        new float[] {5.0f}, 0f);
     
+    private Tree tree;
+    private List<Divider> dividers;
+    private int cellCount, dividerIndex;
+    
     public GridView() {
-        tree = new Tree();
+        dividers = new ArrayList<Divider>();
+        setLayout(new Tree());
     }
     
     public void setLayout(Tree t) {
         this.tree = t;
-        revalidate();
+        cellCount = this.tree.cellCount();
+        validate();
+        repaint();
     }
     
+    public void clear() {
+        tree = null;
+        removeAll();
+    }
+    
+    public Tree getTree() {
+        return tree;
+    }
+    
     public int getCellCount() {
-        return tree.cellCount();
+        return cellCount;
     }
     
     @Override
-    public void doLayout() {  
+    public synchronized void doLayout() {
+        dividerIndex = 0;
         layout(tree, 0, 0, getWidth(), getHeight(), 0);
+        while (dividers.size() > dividerIndex + 1) {
+            Divider d = dividers.get(dividers.size() - 1);
+            dividers.remove(dividers.size() - 1);
+            remove(d);
+        }
     }
+    
+    @Override
+    public synchronized Component add(Component comp) {
+        // add before dividers
+        return super.add(comp, getComponentCount() - dividers.size());
+    }
 
     private int layout(GridView.Tree t, int x, int y, int w, int h, int index) {
+        if (t == null) {
+            return index;
+        }
         if (t.splitType == Tree.NONE) {
-            if (getComponentCount() > index) {
+            if (cellCount > index) {
                 Component c = getComponent(index);
                 c.setSize(w, h);
                 c.setLocation(x, y);
@@ -53,52 +96,41 @@
             return index + 1;
         }
         else if (t.splitType == Tree.V) {
-            int h1 = (int) (t.splitPosition * h) - DIVIDER_SIZE / 2;
-            int h2 = h - h1 - DIVIDER_SIZE;
-            index = layout(t.first, x, y, w, h1, index);
-            return layout(t.second, x, y + h1 + DIVIDER_SIZE, w, h2, index);
+            int h1 = (int) (t.splitPosition * h);
+            int h2 = h - h1;
+            setDivider(Tree.V, x, y + h1 - DIVIDER_SIZE / 2, w, DIVIDER_SIZE, h, t);
+            index = layout(t.first, x, y, w, h1 - DIVIDER_SIZE / 2, index);
+            return layout(t.second, x, y + h1 + DIVIDER_SIZE / 2, w, h2, index);
         }
         else if (t.splitType == Tree.H) {
-            int w1 = (int) (t.splitPosition * w) - DIVIDER_SIZE / 2;
-            int w2 = w - w1 - DIVIDER_SIZE;
-            index = layout(t.first, x, y, w1, h, index);
-            return layout(t.second, x + w1 + DIVIDER_SIZE, y, w2, h, index);
+            int w1 = (int) (t.splitPosition * w);
+            int w2 = w - w1;
+            setDivider(Tree.H, x + w1 - DIVIDER_SIZE / 2, y, DIVIDER_SIZE, h, w, t);
+            index = layout(t.first, x, y, w1 - DIVIDER_SIZE / 2, h, index);
+            return layout(t.second, x + w1 + DIVIDER_SIZE / 2, y, w2, h, index);
         }
         return index;
     }
     
-    private final Stroke DIVIDER_STROKE = new BasicStroke(1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_ROUND, 0, 
-        new float[] {5.0f}, 0f); 
-    
-    
-    @Override
-    public void paint(Graphics g) {
-        super.paint(g);
-        Graphics2D g2 = (Graphics2D) g;
-        g2.setColor(UIManager.getColor("Table.gridColor"));
-        g2.setStroke(DIVIDER_STROKE);
-        paintDivider(g, tree, 0, 0, getWidth(), getHeight());
-    }
-
-    private void paintDivider(Graphics g, Tree t, int x, int y, int w, int h) {
-        if (t == null || t.splitType == Tree.NONE) {
+    private void setDivider(int dir, int x, int y, int w, int h, int range, Tree t) {
+        if (dividers.size() <= dividerIndex) {
+            Divider d = new Divider(dir, x, y, w, h, range, t);
+            dividers.add(d);
+            super.add(d);
         }
-        else if (t.splitType == Tree.V) {
-            int h1 = (int) (t.splitPosition * h);
-            g.drawLine(x, y + h1, x + w, y + h1);
-            paintDivider(g, t.first, x, y, w, h1 - DIVIDER_SIZE / 2);
-            paintDivider(g, t.second, x, y + h1 + DIVIDER_SIZE / 2, w, h1 - DIVIDER_SIZE / 2);
+        else {
+            Divider d = dividers.get(dividerIndex);
+            d.set(dir, x, y, w, h, range, t);
+            d.validate();
         }
-        else if (t.splitType == Tree.H) {
-            int w1 = (int) (t.splitPosition * w);
-            g.drawLine(x + w1, y, x + w1, y + h);
-            paintDivider(g, t.first, x, y, w1 - DIVIDER_SIZE / 2, h);
-            paintDivider(g, t.second, x + w1 + DIVIDER_SIZE / 2, y, w1 - DIVIDER_SIZE / 2, h);
-        }
+        dividerIndex++;
     }
 
-
-
+    private void addDivider(Divider divider) {
+        dividers.add(divider);
+        this.add(divider);
+    } 
+    
     public static class Tree {
         public static final int NONE = 0;
         public static final int H = 1;
@@ -162,6 +194,30 @@
                 return t.copy();
             }
         }
+
+        public void store(Preferences p) {
+            p.putInt("splitType", splitType);
+            p.putDouble("splitPosition", splitPosition);
+            if (first != null) {
+                Preferences p1 = p.node("first");
+                first.store(p1);
+            }
+            if (second != null) {
+                Preferences p2 = p.node("second");
+                second.store(p2);
+            }
+        }
+        
+        public static Tree load(Preferences p) throws BackingStoreException {
+            Tree tree = new Tree();
+            tree.splitType = p.getInt("splitType", H);
+            tree.splitPosition = p.getDouble("splitPosition", 0.5);
+            if (tree.splitType != NONE) {
+                tree.first = load(p.node("first"));
+                tree.second = load(p.node("second"));
+            }
+            return tree;
+        }
     }
     
     private static class TreeIcon extends ImageIcon {
@@ -209,4 +265,123 @@
             }
         }
     }
+    
+    private static class Divider extends JComponent implements MouseListener, MouseMotionListener {
+        private int type, range;
+        private Tree tree;
+        private boolean dragging;
+        private int vd;
+        
+        public Divider(int type, int x, int y, int w, int h, int range, Tree tree) {
+            this.type = type;
+            this.tree = tree;
+            this.range = range;
+            this.setLocation(x, y);
+            this.setSize(w, h);
+            if (type == Tree.H) {
+                this.setCursor(H_RESIZE_CURSOR);
+            }
+            else {
+                this.setCursor(V_RESIZE_CURSOR);
+            }
+            addMouseListener(this);
+            addMouseMotionListener(this);
+        }
+    
+        public void set(int dir, int x, int y, int w, int h, int range, Tree t) {
+            this.type = dir;
+            this.tree = t;
+            this.range = range;
+            setLocation(x, y);
+            setSize(w, h);
+            if (type == Tree.H) {
+                this.setCursor(H_RESIZE_CURSOR);
+            }
+            else {
+                this.setCursor(V_RESIZE_CURSOR);
+            }
+        }
+
+        public void paintComponent(Graphics g) {
+            Graphics2D g2 = (Graphics2D) g;
+            
+            if (dragging) {
+                g2.setColor(UIManager.getColor("Separator.highlight"));
+            }
+            else {
+                g2.setColor(UIManager.getColor("Separator.foreground"));
+            }
+            //g2.setColor(Color.BLACK);
+            g2.setStroke(DIVIDER_STROKE);
+            if (type == Tree.H) {
+                int w2 = getWidth() / 2;
+                g.drawLine(w2, 0, w2, getHeight());
+            }
+            else {
+                int h2 = getHeight() / 2;
+                g.drawLine(0, h2, getWidth(), h2);
+            }
+        }
+
+        @Override
+        public void mouseDragged(MouseEvent e) {
+            int v;
+            if (type == Tree.V) {
+                v = e.getYOnScreen() - vd;
+            }
+            else {
+                v = e.getXOnScreen() - vd;
+            }
+        
+            if (v < 0) {
+                v = 0;
+            }
+            if (v > range) {
+                v = range;
+            }
+            double pos = (double) v / range;
+            tree.splitPosition = pos;
+            getParent().revalidate();
+            getParent().repaint();
+        }
+
+        @Override
+        public void mouseMoved(MouseEvent e) {
+            if (dragging) {
+                mouseDragged(e);
+            }
+        }
+
+        @Override
+        public void mouseClicked(MouseEvent e) {
+        }
+
+        @Override
+        public void mousePressed(MouseEvent e) {
+            dragging = true;
+            if (type == Tree.H) {
+                int w2 = getX() + getWidth() / 2;
+                vd = e.getXOnScreen() - w2;
+            }
+            else {
+                int h2 = getY() + getHeight() / 2;
+                vd = e.getYOnScreen() - h2;
+            }
+            repaint();
+        }
+
+        @Override
+        public void mouseReleased(MouseEvent e) {
+            dragging = false;
+            repaint();
+        }
+
+        @Override
+        public void mouseEntered(MouseEvent e) {
+        }
+
+        @Override
+        public void mouseExited(MouseEvent e) {
+        }
+    }
 }
\ No newline at end of file




More information about the Swift-commit mailing list