diff --git a/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/CalendarNode.java b/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/CalendarNode.java new file mode 100644 index 0000000..550d0cf --- /dev/null +++ b/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/CalendarNode.java @@ -0,0 +1,120 @@ +package edu.umd.cs.piccolo.examples.fisheye; + +import java.awt.Font; + +import edu.umd.cs.piccolo.PNode; +import edu.umd.cs.piccolo.event.PBasicInputEventHandler; +import edu.umd.cs.piccolo.event.PInputEvent; + +class CalendarNode extends PNode { + static int DEFAULT_NUM_DAYS = 7; + static int DEFAULT_NUM_WEEKS = 12; + static int TEXT_X_OFFSET = 1; + static int TEXT_Y_OFFSET = 10; + static int DEFAULT_ANIMATION_MILLIS = 250; + static float FOCUS_SIZE_PERCENT = 0.65f; + static Font DEFAULT_FONT = new Font("Arial", Font.PLAIN, 10); + + int numDays = DEFAULT_NUM_DAYS; + int numWeeks = DEFAULT_NUM_WEEKS; + int daysExpanded = 0; + int weeksExpanded = 0; + + public CalendarNode() { + for (int week = 0; week < numWeeks; week++) { + for (int day = 0; day < numDays; day++) { + addChild(new DayNode(week, day)); + } + } + + CalendarNode.this.addInputEventListener(new PBasicInputEventHandler() { + public void mouseReleased(PInputEvent event) { + DayNode pickedDay = (DayNode) event.getPickedNode(); + if (pickedDay.hasWidthFocus && pickedDay.hasHeightFocus) { + setFocusDay(null, true); + } + else { + setFocusDay(pickedDay, true); + } + } + }); + } + + public void setFocusDay(DayNode focusDay, boolean animate) { + for (int i = 0; i < getChildrenCount(); i++) { + DayNode each = (DayNode) getChild(i); + each.hasWidthFocus = false; + each.hasHeightFocus = false; + } + + if (focusDay == null) { + daysExpanded = 0; + weeksExpanded = 0; + } + else { + focusDay.hasWidthFocus = true; + daysExpanded = 1; + weeksExpanded = 1; + + for (int i = 0; i < numDays; i++) { + getDay(focusDay.week, i).hasHeightFocus = true; + } + + for (int i = 0; i < numWeeks; i++) { + getDay(i, focusDay.day).hasWidthFocus = true; + } + } + + layoutChildren(animate); + } + + public DayNode getDay(int week, int day) { + return (DayNode) getChild((week * numDays) + day); + } + + protected void layoutChildren(boolean animate) { + double focusWidth = 0; + double focusHeight = 0; + + if (daysExpanded != 0 && weeksExpanded != 0) { + focusWidth = (getWidth() * FOCUS_SIZE_PERCENT) / daysExpanded; + focusHeight = (getHeight() * FOCUS_SIZE_PERCENT) / weeksExpanded; + } + + double collapsedWidth = (getWidth() - (focusWidth * daysExpanded)) + / (numDays - daysExpanded); + double collapsedHeight = (getHeight() - (focusHeight * weeksExpanded)) + / (numWeeks - weeksExpanded); + + double xOffset = 0; + double yOffset = 0; + double rowHeight = 0; + DayNode each = null; + + for (int week = 0; week < numWeeks; week++) { + for (int day = 0; day < numDays; day++) { + each = getDay(week, day); + double width = collapsedWidth; + double height = collapsedHeight; + + if (each.hasWidthFocus()) + width = focusWidth; + if (each.hasHeightFocus()) + height = focusHeight; + + if (animate) { + each.animateToBounds(xOffset, yOffset, width, + height, DEFAULT_ANIMATION_MILLIS).setStepRate(0); + } + else { + each.setBounds(xOffset, yOffset, width, height); + } + + xOffset += width; + rowHeight = height; + } + xOffset = 0; + yOffset += rowHeight; + } + } +} diff --git a/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/DayNode.java b/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/DayNode.java new file mode 100644 index 0000000..8e589e7 --- /dev/null +++ b/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/DayNode.java @@ -0,0 +1,77 @@ +package edu.umd.cs.piccolo.examples.fisheye; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.util.ArrayList; + +import edu.umd.cs.piccolo.PNode; +import edu.umd.cs.piccolo.util.PPaintContext; + +class DayNode extends PNode { + boolean hasWidthFocus; + boolean hasHeightFocus; + ArrayList lines; + int week; + int day; + String dayOfMonthString; + + public DayNode(int week, int day) { + lines = new ArrayList(); + lines.add("7:00 AM Walk the dog."); + lines.add("9:30 AM Meet John for Breakfast."); + lines.add("12:00 PM Lunch with Peter."); + lines.add("3:00 PM Research Demo."); + lines.add("6:00 PM Pickup Sarah from gymnastics."); + lines.add("7:00 PM Pickup Tommy from karate."); + this.week = week; + this.day = day; + this.dayOfMonthString = Integer.toString((week * 7) + day); + setPaint(Color.BLACK); + } + + public int getWeek() { + return week; + } + + public int getDay() { + return day; + } + + public boolean hasHeightFocus() { + return hasHeightFocus; + } + + public void setHasHeightFocus(boolean hasHeightFocus) { + this.hasHeightFocus = hasHeightFocus; + } + + public boolean hasWidthFocus() { + return hasWidthFocus; + } + + public void setHasWidthFocus(boolean hasWidthFocus) { + this.hasWidthFocus = hasWidthFocus; + } + + protected void paint(PPaintContext paintContext) { + Graphics2D g2 = paintContext.getGraphics(); + + g2.setPaint(getPaint()); + g2.draw(getBoundsReference()); + g2.setFont(CalendarNode.DEFAULT_FONT); + + float y = (float) getY() + CalendarNode.TEXT_Y_OFFSET; + paintContext.getGraphics().drawString(dayOfMonthString, + (float) getX() + CalendarNode.TEXT_X_OFFSET, y); + + if (hasWidthFocus && hasHeightFocus) { + paintContext.pushClip(getBoundsReference()); + for (int i = 0; i < lines.size(); i++) { + y += 10; + g2.drawString((String) lines.get(i), + (float) getX() + CalendarNode.TEXT_X_OFFSET, y); + } + paintContext.popClip(getBoundsReference()); + } + } +} diff --git a/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/TabularFisheye.java b/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/TabularFisheye.java new file mode 100644 index 0000000..29afe3b --- /dev/null +++ b/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/TabularFisheye.java @@ -0,0 +1,28 @@ +package edu.umd.cs.piccolo.examples.fisheye; + +import java.awt.Dimension; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; + +import edu.umd.cs.piccolo.PCanvas; + +public class TabularFisheye extends PCanvas { + private CalendarNode calendarNode; + + public TabularFisheye() { + calendarNode = new CalendarNode(); + getLayer().addChild(calendarNode); + setMinimumSize(new Dimension(300, 300)); + setPreferredSize(new Dimension(600, 600)); + setZoomEventHandler(null); + setPanEventHandler(null); + + addComponentListener(new ComponentAdapter() { + public void componentResized(ComponentEvent arg0) { + calendarNode.setBounds(getX(), getY(), + getWidth() - 1, getHeight() - 1); + calendarNode.layoutChildren(false); + } + }); + } +} diff --git a/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/TabularFisheyeApplet.java b/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/TabularFisheyeApplet.java new file mode 100644 index 0000000..e6c9f3f --- /dev/null +++ b/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/TabularFisheyeApplet.java @@ -0,0 +1,11 @@ +package edu.umd.cs.piccolo.examples.fisheye; + +import javax.swing.JApplet; + +public class TabularFisheyeApplet extends JApplet { + + public void init() { + getContentPane().add(new TabularFisheye()); + } + +} diff --git a/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/TabularFisheyeFrame.java b/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/TabularFisheyeFrame.java new file mode 100644 index 0000000..77cf58c --- /dev/null +++ b/examples/src/main/java/edu/umd/cs/piccolo/examples/fisheye/TabularFisheyeFrame.java @@ -0,0 +1,19 @@ +package edu.umd.cs.piccolo.examples.fisheye; + +import javax.swing.JFrame; + +public class TabularFisheyeFrame extends JFrame { + public TabularFisheyeFrame() { + setTitle("Piccolo2D Tabular Fisheye"); + + TabularFisheye tabularFisheye = new TabularFisheye(); + getContentPane().add(tabularFisheye); + pack(); + } + + public static void main(String args[]) { + JFrame frame = new TabularFisheyeFrame(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + } +}