/** * Current Account Balances: Graphical Display Applet * @author Robert J Morton * @version 12 July 2000, 23 April 2012 * @copyright July 2000 Robert J Morton (all rights reserved) */ // THE PANEL ON WHICH THE ACCOUNT GRAPH IS DISPLAYED import java.awt.*; // for graphics operations (GUI) import javax.swing.*; // swing GUI widgets library import java.io.*; // for stream handling for the above public class graph extends JPanel { private static final Color bg2 = new Color(112,112,112), // graph background colour bg3 = new Color(160,160,160), // graticule colour fg1 = new Color(255,255,0), // my balance colour fg2 = new Color(0,255,255); // combined balance colour private boolean inflate = false, // inflation-correction on switch leap = false; // true if a leap year is selected private int w = 0, // horizontal distance for each vertical graticule line m = 0, // today's balance in integral pence year = 2001, // currently-selected year H = 0; /* used for both penalty threshold level and account balance for each day */ private DataInputStream D; // data input stream that holds the downloaded account data private maxmin mm; // instance reference to the statistics panel private mscale ms; // instance reference of the money-scale panel private savlim1 sl; graph(savlim1 sl, maxmin mm, mscale ms) { // INSTANCE CONSTRUCTOR this.mm = mm; // instance reference of the max/min statistics panel this.ms = ms; // instance reference of the money-scale panel this.sl = sl; // instance reference of the savlim1 panel } /* Set reference of the data input stream containing the account data set by selyear: returns "true" if selected year is a leap year. */ void setLeap(boolean b){leap = b;} /* Create a data stream D for inputting lines of data from the big byte array B[]in loader.java */ void setD(loader ld){ D = new DataInputStream(new ByteArrayInputStream(ld.getArray())); } void setYear(int yr){year = yr;} // set by selyear: year number eg 2001 void setInfl(boolean b) { // called by selinfl inflate = b; // set whether or not the newly-selected year is a leap year repaint(); // must repaint the graph } // with the appropriate version of the account data public void paint(Graphics g) { if(sl.load) return; // DRAW THE VERTICAL GRATICULE LINES ONTO THE IMAGE img g.setColor(bg2); //set graph background colour g.fillRect(0,0,366,201); //clear the graph area within it g.setColor(bg3); //graticule colour w = 0; // horizontal distance for each vertical graticule line for(int i = 0; i < 12; i++) { // for each month shown int d = ms.getDays(i); // days in this month if(i == 1 && leap) d++; // add a day if leap year february g.drawLine(w, 0, w, 200); // vertical graticule lines w += d; // accumulated number of days } g.drawLine(w,0,w,200); // final vertical graticule line // DRAW THE HORIZONTAL GRATICULE LINES int z = 0; // vertical graticule increment for(int i = 0; i < 6; i++) { // for each £1000 graduation g.drawLine(0, z, w, z); // final horizontal annotation mark z += 40; // accumulated number of £s (scaled) } // DRAW THE RED PENALTY-THRESHOLD LINE H = 300000; // set penalty threshold if(inflate) // if the inflate flag is set H = infln.getInt(H,year); // compute inflated penalty threshold H /= 2500; // rescale H from £s to pixels H = 200 - H; // distance from top of graph to penalty line g.setColor(Color.red); // set colour for penalty threshold g.drawLine(0,H,w,H); // draw savings penalty threshold // PLOT THE GRAPH try { // try for IOException D.reset(); // reset byte array pointer to start of data w = 0; // initial x-bias for day number int prev1 = 0, // previous day's balance for my account only prev2 = 0, // previous day's balance for summed accounts a = 0, // initialise the total balance (integral pence) max = 0, // initialise the maximum balance (integral pence) min = 2000000; // initialise the minimum balance (integral pence) try { // try for End Of File Exception while(true) { // infinite loop broken only by try failure m = 0; // today's balances prev1 = plot(g,prev1,fg1); // plot my account only prev2 = plot(g,prev2,fg2); // plot mine + ruby's balance a += H; // accumulate total pence if(max < H) // trap maximum balance max = H; if(min > H) // trap minimum balance min = H; w++; // increment the day number } } // terminate loop when attempt is made to read past end of byte array catch(EOFException f) { } finally { mm.atualizar(max,min,a,w); // display the statistics panel } } catch(IOException e) { } // readByte() can throw an IOException also } private int plot(Graphics g, int prev, Color c) throws IOException { // read account's next day's balance from the input array int x = (int)D.readInt(); if(x == 0) // don't plot zero balances return x; m += x; // add today's balance to total if(inflate) // if inflation radio button checked, H = infln.getInt(m,year); // compute inflated balance else // otherwise, normal radio button is checked H = m; // so use normal balance int h = H / 2500; // scale to pixels if(h < 0) h = -1; // don't plot below the zero line if(h > 200) h = 200; // don't plot above top of graph int y = 200 - h; // off-set it from y-axis zero /* Provided we are plotting beyond the first day of the year AND this plot is not the same height as the previous plot OR it is the same height AND the account balance is at least zero and less than the maximum the graph can show, then... */ if(w > 0 && (y != prev || (y == prev && h > -1 && h < 201 ))) { /* Set the trace colour to blue and join previous day's balance-plot to this day's balance-plot. */ g.setColor(c); g.drawLine(w-1,prev,w,y); } return y; // return today's balance as previous balance for next pass } }