View Javadoc

1   /*
2   * The contents of this file are subject to the BT "ZEUS" Open Source 
3   * Licence (L77741), Version 1.0 (the "Licence"); you may not use this file 
4   * except in compliance with the Licence. You may obtain a copy of the Licence
5   * from $ZEUS_INSTALL/licence.html or alternatively from
6   * http://www.labs.bt.com/projects/agents/zeus/licence.htm
7   * 
8   * Except as stated in Clause 7 of the Licence, software distributed under the
9   * Licence is distributed WITHOUT WARRANTY OF ANY KIND, either express or 
10  * implied. See the Licence for the specific language governing rights and 
11  * limitations under the Licence.
12  * 
13  * The Original Code is within the package zeus.*.
14  * The Initial Developer of the Original Code is British Telecommunications
15  * public limited company, whose registered office is at 81 Newgate Street, 
16  * London, EC1A 7AJ, England. Portions created by British Telecommunications 
17  * public limited company are Copyright 1996-9. All Rights Reserved.
18  * 
19  * THIS NOTICE MUST BE INCLUDED ON ANY COPY OF THIS FILE
20  */
21  
22  
23  
24  package zeus.visualiser.statistics.charts;
25  
26  import java.util.*;
27  import java.awt.*;
28  import zeus.util.*;
29  import zeus.gui.ColorManager;
30  
31  
32  public class LineGraph implements DrawObject {
33     protected static final int    TYPE1 = 0;
34     protected static final int    TYPE2 = 1;
35     protected static final double TINY = 1E-6;
36     protected static final int    LEFT = 100;
37     protected static final int    STEP = 5;
38     protected static final int    TICK_SIZE = 10;
39     protected static final int    KEY_DEPTH = 20;
40  
41     protected String title;
42     protected Vector bars = new Vector();
43     protected int x, y = 0;
44     protected FontMetrics fm;
45     protected Font font;
46     protected int    gap = 10;
47     protected double max = 0.0, min = 0.0, sum = 0.0;
48     protected int type = -1;
49     protected boolean[] is_valid;
50     protected String[] keys;
51  
52     class Bar { double value; String label; Color color; double[] values; }
53  
54     public LineGraph() {
55     }
56     public LineGraph(double[] values, String[] labels, String title) {
57        setData(values,labels,title);
58     }
59     public LineGraph(double[][] values, String[] labels, String[] keys,
60                      String title) {
61        setData(values,labels,keys,title);
62     }
63  
64     public void setData(double[] values, String[] labels, String title) {
65        type = TYPE1;
66        this.title = title;
67  
68        int pos = 0;
69        bars.removeAllElements();
70        max = min = sum = 0.0;
71        for(int j=0;j<values.length;j++) {
72           if (Math.abs(values[j]-0.0) > TINY) {
73               max = Math.max(max,values[j]);
74               min = Math.min(min,values[j]);
75               Bar bar = new Bar();
76               bar.value = values[j];
77               bar.label = labels[j];
78               bar.color = ColorManager.getColor(pos++);
79               bars.addElement(bar);
80           }
81        }
82     }
83     public void setData(double[][] values, String[] labels,
84                         String[] keys, String title) {
85        type = TYPE2;
86        this.title = title;
87  
88        bars.removeAllElements();
89        max = min = sum = 0.0;
90        is_valid = new boolean[keys.length];
91        this.keys = new String[keys.length];
92        for( int i = 0; i < keys.length; i++ ) {
93           this.keys[i] = keys[i];
94           is_valid[i] = false;
95        }
96        double s;
97        for( int i = 0; i < values.length; i++ ) {
98           s = 0.0;
99           for( int j = 0; j < values[i].length; j++ ) {
100             if (Math.abs(values[i][j]-0.0) > TINY) {
101                is_valid[j] = true;
102                s += values[i][j];
103                max = Math.max(max,values[i][j]);
104                min = Math.min(min,values[i][j]);
105             }
106          }
107          if ( Math.abs(s-0.0) > TINY ) {
108             Bar bar = new Bar();
109             bar.values = new double[values[i].length];
110             for( int k = 0; k < bar.values.length; k++ )
111                bar.values[k] = values[i][k];
112             bar.label = labels[i];
113             bars.addElement(bar);
114          }
115       }
116    }
117 
118    public void drawYourSelf(Graphics g) {
119       font = new Font("Arial", Font.BOLD, 14);
120       fm = g.getFontMetrics(font);
121       g.setFont(font);
122       int w  = fm.stringWidth(title);
123       int h  = fm.getHeight();
124       g.drawString(title,(x-w)/2,h);
125 
126       if ( bars.isEmpty() ) return;
127 
128       int mw = 0;
129       Bar bar;
130       font = new Font("Arial", Font.PLAIN, 12);
131       fm = g.getFontMetrics(font);
132       g.setFont(font);
133       for( int i = 0; i < bars.size(); i++ ) {
134          bar = (Bar) bars.elementAt(i);
135          mw = Math.max(mw,fm.stringWidth(bar.label));
136       }
137       mw += 10;
138       int length = (mw+gap)*bars.size();
139 
140       double max_h = min > 0.0 ? max : Math.abs(max-min);
141 
142       int x0 = 0, y0 = 0, x1, y1, x2, y2, xp, yp, px = 0, py = 0;
143       switch( type ) {
144          case TYPE1:
145             g.drawLine(LEFT,3*h,LEFT,y-2*h);
146             x0 = LEFT;
147             y0 = (int)(3.0*h + (max/max_h)*(y-5.0*h));
148             x1 = x0 + length;
149             y1 = y0;
150             g.drawLine(x0,y0,x1,y1);
151             g.setColor(Color.black);
152             for( int i = 0; i < bars.size(); i++ ) {
153                bar = (Bar) bars.elementAt(i);
154                x1 = x0 + (mw+gap)*i + (mw+gap)/2;
155                y1 = (int)(y0 - (bar.value/max)*(y0-3.0*h));
156                GraphicsSymbol.drawSymbol(g,0,10,x1,y1);
157                if ( i != 0 ) g.drawLine(px,py,x1,y1);
158                px = x1; py = y1;
159                w = fm.stringWidth(bar.label);
160                g.drawString(bar.label,x1-w/2,y0 + h);
161 
162             }
163             break;
164          case TYPE2:
165             g.drawLine(LEFT,3*h,LEFT,y-2*h);
166             x0 = LEFT;
167             y0 = (int)(3.0*h + (max/max_h)*(y-5.0*h));
168             x1 = x0 + length;
169             y1 = y0;
170             g.drawLine(x0,y0,x1,y1);
171             for( int j = 0; j < keys.length; j++ ) {
172                for( int i = 0; i < bars.size(); i++ ) {
173                   bar = (Bar) bars.elementAt(i);
174                   x1 = x0 + (mw+gap)*i + (mw+gap)/2;
175                   y1 = (int)(y0 - (bar.values[j]/max)*(y0-3.0*h));
176                   g.setColor(ColorManager.getColor(j));
177                   GraphicsSymbol.drawSymbol(g,j,10,x1,y1);
178                   if ( i != 0 ) g.drawLine(px,py,x1,y1);
179                   px = x1; py = y1;
180                }
181             }
182             for( int i = 0; i < bars.size(); i++ ) {
183                bar = (Bar) bars.elementAt(i);
184                x1 = x0 + (mw+gap)*i + (mw+gap)/2;
185                w = fm.stringWidth(bar.label);
186                g.setColor(Color.black);
187                g.drawString(bar.label,x1-w/2,y0+h);
188             }
189             break;
190          default:
191             return;
192       }
193       // draw y-scale
194       double v, dv;
195       dv = (max/STEP);
196       dv = ((int)(dv+0.51) == 0) ? dv : (double)((int)(dv+0.51));
197       int step = (int)((y0-3.0*h)*dv/max);
198       g.setColor(Color.black);
199       v = 0.0;
200       xp = x0; yp = y0;
201       while( v-TINY <= max ) {
202          String yval = Misc.decimalPlaces(v,2);
203          g.drawLine(xp,yp,xp-TICK_SIZE,yp);
204          w = fm.stringWidth(yval);
205          g.drawString(yval,xp-TICK_SIZE-w-5,yp);
206          v += dv;
207          yp -= step;
208       }
209       if ( min < 0.0 ) {
210          v = -dv;
211          xp = x0; yp = y0 + step;
212          while( v > min ) {
213             String yval = Misc.decimalPlaces(v,2);
214             g.drawLine(xp,yp,xp-TICK_SIZE,yp);
215             w = fm.stringWidth(yval);
216             g.drawString(yval,xp-TICK_SIZE-w-5,yp);
217             v -= dv;
218             yp += step;
219          }
220       }
221       // add key
222       if ( type == TYPE2 ) {
223          x1 = x0 + length + LEFT; y1 = 3*h;
224          h = fm.getHeight();
225          int dh = Math.max(h+10,KEY_DEPTH);
226          g.setColor(Color.black);
227          g.drawString("Key",x1,y1);
228          for( int i = 0; i < keys.length; i++ ) {
229             if ( is_valid[i] ) {
230                y1 += dh;
231                g.setColor(ColorManager.getColor(i));
232                GraphicsSymbol.drawSymbol(g,i,10,x1+(dh-3)/2,y1+(dh-3)/2);
233                g.setColor(Color.black);
234                g.drawString(keys[i],x1+dh,y1+(dh-3)/2);
235             }
236          }
237       }
238    }
239    public void setXY(int xc, int yc) {
240       x = xc; y = yc;
241    }
242 
243 }