import processing.xml.*; int[][] dataSet; int[][] dataSet2; // percentage XMLElement xml; int sliderValue; int vRadius; HScrollbar slider; PFont font; // about 19 records int canvasWidth = 600; int canvasHeight = 500; int startX = 30; int startY = 30; int gutterX = 200; int gutterY = 180; /* 1988 1078 576 11488 2021 2138 1468 229 1485 4445 42370 */ int numFields = 11; String[] fieldName = { "Year", "China", "India", "Japan", "Korea", "New Zealand", "Taiwan", "UAE", "UK", "USA", "Total" }; void loadData(){ XMLElement vRecord, vCell; xml = new XMLElement(this, "export.xml"); int numRecords = xml.getChildCount(); //println(numRecords); dataSet = new int[numRecords][numFields]; dataSet2 = new int[numRecords][numFields]; for (int i = 0; i < numRecords; i++) { vRecord = xml.getChild(i); for (int j = 0; j < numFields ; j++) { vCell = vRecord.getChild(j); dataSet[i][j] = int(vCell.getContent()); } for (int j = 1; j < numFields-1 ; j++) { // normalize to percentage dataSet2[i][j] = int((float)dataSet[i][j]*100.0/dataSet[i][numFields-1]); } } } int backgroundColor = color(207,207,207); int foregroundColor = color(80,120,140); int textColor = color(128,128,0); void setup() { smooth(); loadData(); font = loadFont("TheSans-Plain-12.vlw"); textFont(font, 12); size( canvasWidth+80, canvasHeight+100 ); background( backgroundColor ); fill( foregroundColor ); noStroke(); ellipse(300, 200, 100, 100); slider = new HScrollbar(startX, startY, canvasWidth, 20, 1); } float slideVal; int ix, iy, posx, posy, rowIdx; void drawCircles(){ background( backgroundColor ); slider.update(); slider.display(); noStroke(); fill( foregroundColor ); slideVal = slider.getPos(); // between 0 and canvasWidth ==> map it to idx 0-18 (1988-2006) rowIdx = floor( (float)slideVal*18/canvasWidth ); // 0-18 textAlign(LEFT); fill( textColor ); text( str(rowIdx+1988), startX+canvasWidth+10, startY); textAlign(CENTER); for (int j = 1; j < numFields-1 ; j++) { ix = (j-1)%3; iy = (j-1)/3; posx = ix*gutterX+gutterX/2+startX; posy = iy*gutterY+gutterY/2+startY; vRadius = dataSet2[rowIdx][j]*4+10; // 1 to 25 (percentage) fill( foregroundColor ); ellipse(posx, posy, vRadius, vRadius); fill( textColor ); text(fieldName[j], posx, posy+gutterY/2-14); text( "AUD "+str(dataSet[rowIdx][j])+"m ("+str(dataSet2[rowIdx][j])+"%)", posx, posy+gutterY/2); } } void draw(){ drawCircles(); } class HScrollbar { int swidth, sheight; // width and height of bar int xpos, ypos; // x and y position of bar float spos, newspos; // x position of slider int sposMin, sposMax; // max and min values of slider int loose; // how loose/heavy boolean over; // is the mouse over the slider? boolean locked; float ratio; HScrollbar (int xp, int yp, int sw, int sh, int l) { swidth = sw; sheight = sh; int widthtoheight = sw - sh; ratio = (float)sw / (float)widthtoheight; xpos = xp; ypos = yp-sheight/2; spos = xpos + swidth/2 - sheight/2; newspos = spos; sposMin = xpos; sposMax = xpos + swidth - sheight; loose = l; } void update() { if(over()) { over = true; } else { over = false; } if(mousePressed && over) { locked = true; } if(!mousePressed) { locked = false; } if(locked) { newspos = constrain(mouseX-sheight/2, sposMin, sposMax); } if(abs(newspos - spos) > 1) { spos = spos + (newspos-spos)/loose; } } int constrain(int val, int minv, int maxv) { return min(max(val, minv), maxv); } boolean over() { if(mouseX > xpos && mouseX < xpos+swidth && mouseY > ypos && mouseY < ypos+sheight) { return true; } else { return false; } } void display() { fill(255); rect(xpos, ypos, swidth, sheight); if(over || locked) { fill(153, 102, 0); } else { fill(102, 102, 102); } rect(spos, ypos, sheight, sheight); } float getPos() { // Convert spos to be values between // 0 and the total width of the scrollbar return spos * ratio; } }