summaryrefslogtreecommitdiffstats
path: root/docs/teaching/demos/figures
diff options
context:
space:
mode:
authormkersten <mkersten>2003-11-10 19:11:18 +0000
committermkersten <mkersten>2003-11-10 19:11:18 +0000
commitebfe0a1a9adfe64e41349167d4e3b5b188512d58 (patch)
tree188d7763530ed735b65875a302d5dfdd7ddcc7f4 /docs/teaching/demos/figures
parentd54f21bbd778d29fd2cd1bdbe14402aa7a15551e (diff)
downloadaspectj-ebfe0a1a9adfe64e41349167d4e3b5b188512d58.tar.gz
aspectj-ebfe0a1a9adfe64e41349167d4e3b5b188512d58.zip
Adding scrubbed demos (figures & spacewar), scripts, slides, and Eclipse project configurations.
Diffstat (limited to 'docs/teaching/demos/figures')
-rw-r--r--docs/teaching/demos/figures/.classpath7
-rw-r--r--docs/teaching/demos/figures/.project19
-rw-r--r--docs/teaching/demos/figures/build.xml15
-rw-r--r--docs/teaching/demos/figures/readme.html299
-rw-r--r--docs/teaching/demos/figures/scratch/HistoryUpdating.java27
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/Box.java55
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/Canvas.java15
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/ColorControl.java20
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/FigureElement.java21
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/Group.java88
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/Line.java70
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/Point.java59
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/ShapeFigureElement.java38
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/SlothfulPoint.java42
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/gui/FigurePanel.java172
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/gui/LogAdapter.java16
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/gui/Main.java25
-rw-r--r--docs/teaching/demos/figures/src-fresh/figures/support/Log.java36
-rw-r--r--docs/teaching/demos/figures/src/figures/Box.java55
-rw-r--r--docs/teaching/demos/figures/src/figures/Canvas.java15
-rw-r--r--docs/teaching/demos/figures/src/figures/ColorControl.java16
-rw-r--r--docs/teaching/demos/figures/src/figures/FigureElement.java21
-rw-r--r--docs/teaching/demos/figures/src/figures/Group.java88
-rw-r--r--docs/teaching/demos/figures/src/figures/Line.java70
-rw-r--r--docs/teaching/demos/figures/src/figures/Point.java59
-rw-r--r--docs/teaching/demos/figures/src/figures/ShapeFigureElement.java38
-rw-r--r--docs/teaching/demos/figures/src/figures/SlothfulPoint.java42
-rw-r--r--docs/teaching/demos/figures/src/figures/gui/FigurePanel.java172
-rw-r--r--docs/teaching/demos/figures/src/figures/gui/LogAdapter.java16
-rw-r--r--docs/teaching/demos/figures/src/figures/gui/Main.java25
-rw-r--r--docs/teaching/demos/figures/src/figures/support/HistoryUpdating.aj27
-rw-r--r--docs/teaching/demos/figures/src/figures/support/Log.java36
32 files changed, 1704 insertions, 0 deletions
diff --git a/docs/teaching/demos/figures/.classpath b/docs/teaching/demos/figures/.classpath
new file mode 100644
index 000000000..8ae844dbf
--- /dev/null
+++ b/docs/teaching/demos/figures/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="lib" path="C:/AspectJ-Demo/apps/eclipse-3.0/plugins/org.aspectj.ajde_1.1.4/aspectjrt.jar"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/docs/teaching/demos/figures/.project b/docs/teaching/demos/figures/.project
new file mode 100644
index 000000000..ccc6028ef
--- /dev/null
+++ b/docs/teaching/demos/figures/.project
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>figures</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.ajdt.ui.ajbuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.ajdt.ui.ajnature</nature>
+ <nature>org.eclipse.ajdt.ui.ajnature</nature>
+ </natures>
+</projectDescription>
diff --git a/docs/teaching/demos/figures/build.xml b/docs/teaching/demos/figures/build.xml
new file mode 100644
index 000000000..2816008dc
--- /dev/null
+++ b/docs/teaching/demos/figures/build.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?>
+<!-- writen for Ant 1.5.1 -->
+<project name="figures" default="reset">
+
+<target name="reset" description="Reset the demonstration system sources">
+
+ <delete>
+ <fileset dir="src"/>
+ </delete>
+ <copy todir="src">
+ <fileset dir="src-fresh"/>
+ </copy>
+</target>
+
+</project> \ No newline at end of file
diff --git a/docs/teaching/demos/figures/readme.html b/docs/teaching/demos/figures/readme.html
new file mode 100644
index 000000000..49e59396e
--- /dev/null
+++ b/docs/teaching/demos/figures/readme.html
@@ -0,0 +1,299 @@
+
+<head>
+<style>
+<!--
+ table.MsoNormalTable
+ {mso-style-parent:"";
+ font-size:10.0pt;
+ font-family:"Times New Roman";
+ }
+-->
+</style>
+<STYLE TYPE="text/css">
+<!--
+
+ /* FOR THE SDA PAGE */
+
+ /*
+ BODY {margin-top: 15px; margin-left: 15px; margin-right: 15px;}
+ */
+
+ A:link {
+ color:#4756AC;
+ }
+ A:visited {
+ color:#60657B;
+ }
+ A:hover {
+ color:red
+ }
+
+ INPUT {font:12px "Courier New", sans-serif;}
+
+ H2 {
+ font:18px/18px Verdana, Arial, Helvetica, sans-serif;
+ color:black;
+ font-weight:bold;
+ margin-left: 10px;
+ line-height:110%;
+ }
+ H3 {
+ font:18px/18px Verdana, Arial, Helvetica, sans-serif;
+ color:black;
+ font-weight:bold;
+ margin-left: 10px;
+ line-height:110%;
+ }
+ H4 {
+ font:15px/16px Verdana, Arial, Helvetica, sans-serif;
+ color:black;
+ font-weight:bold;
+ margin-left: 10px;
+ line-height:140%;
+ }
+ P {
+ font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+ margin-right: 10px;
+ margin-left: 10px;
+ line-height:130%;
+ }
+ .paragraph {
+ font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+ margin-right: 10px;
+ margin-left: 10px;
+ line-height:130%;
+ }
+ .smallParagraph {
+ font:11px/11px Verdana, Arial, Helvetica, sans-serif;
+ margin-right: 10px;
+ margin-left: 10px;
+ line-height:130%;
+ }
+ LI {
+ font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+ text-align:justify;
+ margin-right: 10px;
+ margin-left: 15px;
+ line-height:120%;
+ }
+ /*
+ UL {
+ font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+ text-align:justify;
+ margin-right: 10px;
+ margin-left: 15px;
+ line-height:120%;
+ }*/
+
+ DL {
+ font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+ text-align:justify;
+ margin-right: 10px;
+ margin-left: 15px;
+ line-height:120%;
+ }
+ B { font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+ font-weight:bold;
+ line-height:140%;
+ }
+ .footer {
+ font:10px/10px Verdana, Arial, Helvetica, sans-serif;
+ color:#888888;
+ text-align:left
+ }
+ .figureTitle {
+ font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+ text-align:justify;
+ text-align:center
+ }
+ .copyrightNotice {
+ font:10px/10px Verdana, Arial, Helvetica, sans-serif;
+ color:#999999;
+ line-height:110%;
+ }
+ .smallHeading {
+ font:13px/13px Verdana, Arial, Helvetica, sans-serif;
+ font-weight:bold;
+ line-height:110%;
+ }
+ .tinyHeading {
+ font:11px/11px Verdana, Arial, Helvetica, sans-serif;
+ font-weight:bold;
+ line-height:120%;
+ }
+ .newsText {
+ font:11px/11px Verdana, Arial, Helvetica, sans-serif;
+ line-height:130%;
+ }
+ .smallParagraph {
+ font:11px/11px Verdana, Arial, Helvetica, sans-serif;
+ line-height:130%;
+ }
+ .fancyHeading {
+ font:20px/20px Chantilly, Arial, Helvetica, sans-serif;
+ margin-right: 10px;
+ color:#6f7a92;
+ margin-left: 10px;
+ line-height:130%;
+ }
+
+-->
+</STYLE>
+</head>
+
+<h2 align="center">AspectJ Figures Demo Instructions</h2>
+<h4>Setup</h4>
+<ul>
+ <li>
+ <p style="text-align: left">src: contains the end result of the demo, with the Canvas.updateHistory()
+ call refactored into the src/figures/support/HistoryUpdating.aj aspect</li>
+ <li>
+ <p style="text-align: left">src-fresh: contains the plain Java sources that the demo starts with</li>
+</ul>
+<h4>Reset </h4>
+<ul>
+ <li>run the &quot;reset&quot; target in build.xml to reset overwrite the sources in
+ src with those in src-fresh</li>
+</ul>
+<h4>Script</h4>
+<div align="center">
+ <table class="MsoNormalTable" border="0" cellspacing="3" cellpadding="0" style="width: 531.65pt; margin-left: -7.95pt" id="table1">
+ <tr style="height: 33.45pt">
+ <td style="width: 231px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">Show Figure editor running</span></p>
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">Inspect Point.java</span></p>
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">Use joinpoint probe or Eclipse search to find calls</span></td>
+ <td style="width: 461px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">call(void
+ figures.Canvas.updateHistory())</font></span></td>
+ </tr>
+ <tr style="height: 33.45pt">
+ <td style="width: 231px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">Describe places that it’s called</span></p>
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">create aspect (defines a special class that can crosscut other
+ classes)</span></p>
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">aspect HistoryUpdating </span></p>
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">write pointcut (has name and parameters)</span></td>
+ <td style="width: 461px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">pointcut moves():
+ </font> </span></p>
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">&nbsp;&nbsp;&nbsp; execution(void
+ Line.setP1(Point)) || </font> </span></p>
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">&nbsp;&nbsp;&nbsp; execution(void
+ Line.setP2(Point));</font></span></td>
+ </tr>
+ <tr style="height: 33.45pt">
+ <td style="width: 231px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">write after advice (runs “on the way back out”)</span></td>
+ <td style="width: 461px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">after() returning: move() { <br>
+ &nbsp;&nbsp; &lt;runs after each move&gt; }</font></span></td>
+ </tr>
+ <tr style="height: 33.45pt">
+ <td style="width: 231px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">extend advice to Point setters (multi-class)</span></td>
+ <td style="width: 461px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">call(void FigureElement+.set*(..))</font></span></td>
+ </tr>
+ <tr style="height: 33.45pt">
+ <td style="width: 231px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">capture context &amp; use interface</span></td>
+ <td style="width: 461px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">move(FigureElement fe):
+ this(fe)
+ &amp;&amp;..</font></span></td>
+ </tr>
+ <tr style="height: 33.45pt">
+ <td style="width: 231px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">Show structure, note that SlothfulPoint is now included</span></p>
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">Run &amp; show effect</span></td>
+ <td style="width: 461px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">&nbsp;</font></span></td>
+ </tr>
+ <tr style="height: 33.45pt">
+ <td style="width: 231px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">Show Point.moveBy history violoation</span></p>
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">Want to make sure that sets of private fields of classes implementing
+ FigureElement only happen from within the set methods</span></td>
+ <td style="width: 461px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">declare warning:
+ </font> </span></p>
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">&nbsp;&nbsp;&nbsp; set(private * FigureElement+.*) &nbsp;<br>
+&nbsp;&nbsp;&nbsp; &amp;&amp; !(withincode(*
+ FigureElement+.set*(..)) || <br>
+&nbsp;&nbsp;&nbsp; withincode(FigureElement+.new(..))):</font></span></p>
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family: Courier"><font size="1">&nbsp;&nbsp;&nbsp; &quot;should only assign to fields
+ from set methods&quot;;</font></span></td>
+ </tr>
+ <tr style="height: 33.45pt">
+ <td style="width: 231px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="text-indent: -.25in; margin-left: 40.5pt">
+ <span style="font-size: 10.0pt; font-family: Symbol">·<span style="font:7.0pt &quot;Times New Roman&quot;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+ </span></span><span style="font-size:10.0pt;font-family:
+ Tahoma">Write before advice that does precondition checking on Points.</span></td>
+ <td style="width: 461px; height: 33.45pt; padding: 1.5pt; background: #F7F7F7">
+ <p class="MsoNormal" style="margin-left:7.5pt">
+ <span style="font-family:&quot;Courier New&quot;"><font size="2">before(int</font><font size="2">
+ newValue): <br>
+ &nbsp;&nbsp;&nbsp; set(int Point.*) &amp;&amp; args(newValue) {<br>
+ &nbsp;&nbsp;&nbsp; if (newValue &lt; 0) {<br>
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new IAE(&quot;too small&quot;);<br>
+ &nbsp;&nbsp;&nbsp; } <br>
+ }</font></span></td>
+ </tr>
+ </table>
+</div>
+<p>&nbsp;</p>
diff --git a/docs/teaching/demos/figures/scratch/HistoryUpdating.java b/docs/teaching/demos/figures/scratch/HistoryUpdating.java
new file mode 100644
index 000000000..f4eff3d3f
--- /dev/null
+++ b/docs/teaching/demos/figures/scratch/HistoryUpdating.java
@@ -0,0 +1,27 @@
+package figures.support;
+
+import figures.*;
+
+public aspect HistoryUpdating {
+
+ pointcut moves(FigureElement fe):
+ this(fe) &&
+ execution(void FigureElement+.set*(..));
+
+ after(FigureElement fe) returning: moves(fe) {
+ Canvas.updateHistory(fe);
+ }
+
+ declare error:
+ set(private * FigureElement+.*) &&
+ !(withincode(void FigureElement+.set*(..)) ||
+ withincode(FigureElement+.new(..))):
+ "doh!!!";
+
+ before(int newValue):
+ set(int Point.*) && args(newValue) {
+ if (newValue < 0) {
+ throw new IllegalArgumentException("too small");
+ }
+ }
+}
diff --git a/docs/teaching/demos/figures/src-fresh/figures/Box.java b/docs/teaching/demos/figures/src-fresh/figures/Box.java
new file mode 100644
index 000000000..4db7f439d
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/Box.java
@@ -0,0 +1,55 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Box extends ShapeFigureElement {
+ private Point _p0;
+ private Point _p1;
+ private Point _p2;
+ private Point _p3;
+
+ public Box(int x0, int y0, int width, int height) {
+ _p0 = new Point(x0, y0);
+ _p1 = new Point(x0+width, y0);
+ _p2 = new Point(x0+width, y0+height);
+ _p3 = new Point(x0, y0+height);
+ }
+
+ public Point getP0() { return _p0; }
+ public Point getP1() { return _p1; }
+ public Point getP2() { return _p2; }
+ public Point getP3() { return _p3; }
+
+ public void move(int dx, int dy) {
+ _p0.move(dx, dy);
+ _p1.move(dx, dy);
+ _p2.move(dx, dy);
+ _p3.move(dx, dy);
+ }
+
+ public void checkBoxness() {
+ if ((_p0.getX() == _p3.getX()) &&
+ (_p1.getX() == _p2.getX()) &&
+ (_p0.getY() == _p1.getY()) &&
+ (_p2.getY() == _p3.getY()))
+ return;
+ throw new IllegalStateException("This is not a square.");
+ }
+
+ public String toString() {
+ return "Box(" + _p0 + ", " + _p1 + ", " + _p2 + ", " + _p3 + ")";
+ }
+
+ public Shape getShape() {
+ return new Rectangle(getP1().getX(),
+ getP1().getY(),
+ getP3().getX() - getP1().getX(),
+ getP3().getY() - getP1().getY());
+ }
+}
+
diff --git a/docs/teaching/demos/figures/src-fresh/figures/Canvas.java b/docs/teaching/demos/figures/src-fresh/figures/Canvas.java
new file mode 100644
index 000000000..ef849a5d5
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/Canvas.java
@@ -0,0 +1,15 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import figures.support.Log;
+
+public class Canvas {
+ public static void updateHistory() { }
+
+ public static void updateHistory(FigureElement fe) {
+ System.out.println("> updating history for: " + fe);
+ }
+}
diff --git a/docs/teaching/demos/figures/src-fresh/figures/ColorControl.java b/docs/teaching/demos/figures/src-fresh/figures/ColorControl.java
new file mode 100644
index 000000000..46d1ba428
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/ColorControl.java
@@ -0,0 +1,20 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.Color;
+import figures.FigureElement;
+
+public aspect ColorControl {
+ public static void setFillColor(FigureElement fe, Color color) {
+ // fill in here
+ }
+
+ public static void setLineColor(FigureElement fe, Color color) {
+ // fill in here
+ }
+
+ // fill in here
+}
diff --git a/docs/teaching/demos/figures/src-fresh/figures/FigureElement.java b/docs/teaching/demos/figures/src-fresh/figures/FigureElement.java
new file mode 100644
index 000000000..ae06c132b
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/FigureElement.java
@@ -0,0 +1,21 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public interface FigureElement {
+ public static final int MIN_VALUE = 0;
+ public static final int MAX_VALUE = 500;
+
+ public abstract void move(int dx, int dy);
+
+ public abstract Rectangle getBounds();
+
+ public abstract boolean contains(Point2D p);
+
+ public abstract void paint(Graphics2D g2);
+}
diff --git a/docs/teaching/demos/figures/src-fresh/figures/Group.java b/docs/teaching/demos/figures/src-fresh/figures/Group.java
new file mode 100644
index 000000000..59c1a17cf
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/Group.java
@@ -0,0 +1,88 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Group implements FigureElement {
+ private Collection _members;
+ private String _identifier;
+
+ public Group(FigureElement first) {
+ this._members = new ArrayList();
+ add(first);
+ }
+
+ public void add(FigureElement fe) {
+ _members.add(fe);
+ }
+
+ public Iterator members() {
+ return _members.iterator();
+ }
+
+ public void move(int dx, int dy) {
+ for (Iterator i = _members.iterator(); i.hasNext(); ) {
+ FigureElement fe = (FigureElement)i.next();
+ fe.move(dx, dy);
+ }
+ }
+
+ public void resetIdentifier(String identifier) {
+ resetIdentifier(identifier);
+ }
+
+ public String toString() {
+ if (_identifier != null) {
+ return _identifier;
+ }
+
+ StringBuffer buf = new StringBuffer("Group(");
+ for (Iterator i = _members.iterator(); i.hasNext(); ) {
+ buf.append(i.next().toString());
+ if (i.hasNext()) {
+ buf.append(", ");
+ }
+ }
+ buf.append(")");
+ return buf.toString();
+ }
+
+ public Rectangle getBounds() {
+ Rectangle previous = null;
+ for (Iterator i = _members.iterator(); i.hasNext(); ) {
+ FigureElement fe = (FigureElement)i.next();
+ Rectangle rect = fe.getBounds();
+ if (previous != null) {
+ previous = previous.union(rect);
+ } else {
+ previous = rect;
+ }
+ }
+ return previous;
+ }
+
+ public boolean contains(Point2D p) {
+ for (Iterator i = _members.iterator(); i.hasNext(); ) {
+ FigureElement fe = (FigureElement)i.next();
+ if (fe.contains(p)) return true;
+ }
+ return false;
+ }
+
+ public void paint(Graphics2D g2) {
+ for (Iterator i = _members.iterator(); i.hasNext(); ) {
+ FigureElement fe = (FigureElement)i.next();
+ fe.paint(g2);
+ }
+ }
+
+ public int size() {
+ return _members.size();
+ }
+}
+
diff --git a/docs/teaching/demos/figures/src-fresh/figures/Line.java b/docs/teaching/demos/figures/src-fresh/figures/Line.java
new file mode 100644
index 000000000..e76206639
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/Line.java
@@ -0,0 +1,70 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Line extends ShapeFigureElement {
+ private Point _p1;
+ private Point _p2;
+
+ public Line(Point p1, Point p2) {
+ _p1 = p1;
+ _p2 = p2;
+ }
+
+ public Point getP1() {
+ return _p1;
+ }
+
+ public void setP1(Point p1) {
+ _p1 = p1;
+ Canvas.updateHistory();
+ }
+
+ public Point getP2() {
+ return _p2;
+ }
+
+ public void setP2(Point p2) {
+ _p2 = p2;
+ Canvas.updateHistory();
+ }
+
+ public void move(int dx, int dy) {
+ _p1.move(dx, dy);
+ _p2.move(dx, dy);
+ }
+
+ public String toString() {
+ return "Line(" + _p1 + ", " + _p2 + ")";
+ }
+
+ /**
+ * Used to determine if this line {@link contains(Point2D)} a point.
+ */
+ final static int THRESHHOLD = 5;
+
+ /**
+ * Returns <code>true</code> if the point segment distance is less than
+ * {@link THRESHHOLD}.
+ */
+ public boolean contains(Point2D p) {
+ return getLine2D().ptLineDist(p) < THRESHHOLD;
+ }
+
+ private Line2D getLine2D() {
+ return new Line2D.Float((float)getP1().getX(),
+ (float)getP1().getY(),
+ (float)getP2().getX(),
+ (float)getP2().getY());
+ }
+
+ public Shape getShape() {
+ return getLine2D();
+ }
+}
+
diff --git a/docs/teaching/demos/figures/src-fresh/figures/Point.java b/docs/teaching/demos/figures/src-fresh/figures/Point.java
new file mode 100644
index 000000000..9699aaf31
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/Point.java
@@ -0,0 +1,59 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Point extends ShapeFigureElement {
+ private int _x;
+ private int _y;
+
+ public Point(int x, int y) {
+ _x = x;
+ _y = y;
+ }
+
+ public int getX() {
+ return _x;
+ }
+
+ public void setX(int x) {
+ _x = x;
+ Canvas.updateHistory();
+ }
+
+ public int getY() {
+ return _y;
+ }
+
+ public void setY(int y) {
+ _y = y;
+ Canvas.updateHistory();
+ }
+
+ public void move(int dx, int dy) {
+ _x += dx;
+ _y += dy;
+ }
+
+ public String toString() {
+ return "Point(" + _x + ", " + _y + ")";
+ }
+
+ /** The height of displayed {@link Point}s. */
+ private final static int HEIGHT = 10;
+
+ /** The width of displayed {@link Point}s. -- same as {@link HEIGHT}. */
+ private final static int WIDTH = Point.HEIGHT;
+
+ public Shape getShape() {
+ return new Ellipse2D.Float((float)getX()-Point.WIDTH/2,
+ (float)getY()-Point.HEIGHT/2,
+ (float)Point.HEIGHT,
+ (float)Point.WIDTH);
+ }
+}
+
diff --git a/docs/teaching/demos/figures/src-fresh/figures/ShapeFigureElement.java b/docs/teaching/demos/figures/src-fresh/figures/ShapeFigureElement.java
new file mode 100644
index 000000000..29a4a89ad
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/ShapeFigureElement.java
@@ -0,0 +1,38 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public abstract class ShapeFigureElement implements FigureElement {
+ public abstract void move(int dx, int dy);
+
+ public abstract Shape getShape();
+
+ public Rectangle getBounds() {
+ return getShape().getBounds();
+ }
+
+ public boolean contains(Point2D p) {
+ return getShape().contains(p);
+ }
+
+ public Color getLineColor() {
+ return Color.black;
+ }
+
+ public Color getFillColor() {
+ return Color.red;
+ }
+
+ public final void paint(Graphics2D g2) {
+ Shape shape = getShape();
+ g2.setPaint(getFillColor());
+ g2.fill(shape);
+ g2.setPaint(getLineColor());
+ g2.draw(shape);
+ }
+}
diff --git a/docs/teaching/demos/figures/src-fresh/figures/SlothfulPoint.java b/docs/teaching/demos/figures/src-fresh/figures/SlothfulPoint.java
new file mode 100644
index 000000000..620970373
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/SlothfulPoint.java
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+/**
+ * This class makes mistakes to be caught by invariant checkers.
+ */
+public class SlothfulPoint extends ShapeFigureElement {
+ private int _x;
+ private int _y;
+
+ public SlothfulPoint(int x, int y) {
+ }
+
+ public void setX(int x) {
+ _x = x;
+ }
+
+ public void setY(int y) {
+ _y = y;
+ }
+
+ public void move(int dx, int dy) {
+ setX(_x + dx);
+ setY(_y + dy);
+ }
+
+ public String toString() {
+ return "SlothfulPoint";
+ }
+
+ public Shape getShape() {
+ return new Ellipse2D.Float((float)_x,
+ (float)_y, 1.0f, 1.0f);
+ }
+}
+
diff --git a/docs/teaching/demos/figures/src-fresh/figures/gui/FigurePanel.java b/docs/teaching/demos/figures/src-fresh/figures/gui/FigurePanel.java
new file mode 100644
index 000000000..cac59e835
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/gui/FigurePanel.java
@@ -0,0 +1,172 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures.gui;
+
+import figures.Point;
+import figures.Line;
+import figures.FigureElement;
+import figures.Group;
+
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.text.*;
+import javax.swing.border.*;
+
+public class FigurePanel extends JComponent {
+
+ ButtonsPanel bp = new ButtonsPanel();
+ FigureSurface fs = new FigureSurface();
+ ConsolePanel cp = new ConsolePanel();
+
+
+ public FigurePanel() {
+ setLayout(new BorderLayout());
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ panel.add(fs);
+ panel.add(bp);
+ JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, panel, cp);
+ sp.setPreferredSize(new Dimension(500, 400));
+ sp.setDividerLocation(250);
+ add(BorderLayout.CENTER, sp);
+ }
+
+ class ButtonsPanel extends JPanel {
+ private JLabel msgs = new JLabel("click to add a point or line");
+ public ButtonsPanel() {
+ setLayout(new FlowLayout(FlowLayout.LEFT));
+// add(new JButton(new AbstractAction("Main") {
+// public void actionPerformed(ActionEvent e) {
+// Main.main(new String[]{});
+// fs.repaint();
+// }
+// }));
+ add(msgs);
+ }
+
+ public void log(String msg) {
+ msgs.setText(msg);
+ }
+ }
+
+ static class ConsolePanel extends JPanel {
+
+ JTextArea text = new JTextArea();
+
+ public ConsolePanel() {
+ super(new BorderLayout());
+ text.setFont(StyleContext.getDefaultStyleContext().getFont("SansSerif", Font.PLAIN, 10));
+ JScrollPane scroller = new JScrollPane(text);
+ scroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ add(BorderLayout.CENTER, scroller);
+ }
+
+ public void println(String msg) {
+ text.append(msg + '\n');
+ }
+ }
+
+ final static Color BACKGROUND = Color.white;
+
+ static class FigureSurface extends JPanel implements MouseListener, MouseMotionListener {
+ private Group canvas;
+
+ public FigureSurface() {
+ canvas = new Group(new Point(250, 250));
+ addMouseMotionListener(this);
+ addMouseListener(this);
+ setPreferredSize(new Dimension(500,500));
+ }
+
+ private Point addPoint(int x, int y) {
+ Point p = new Point(x, y);
+ canvas.add(p);
+ repaint();
+ return p;
+ }
+
+ private Line addLine(Point p1, Point p2) {
+ if (Math.abs(p1.getX()-p2.getX()) < 5 ||
+ Math.abs(p1.getY()-p2.getY()) < 5) {
+ return null;
+ }
+
+ Line line = null;
+ if (p1 != null && p2 != null) {
+ line = new Line(p1, p2);
+ canvas.add(line);
+ }
+ repaint();
+ return line;
+ }
+
+ public void paint(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setPaint(BACKGROUND);
+ g2.fill(new Rectangle2D.Float(0f, 0f, (float)g2.getClipBounds().width, (float)g2.getClipBounds().height));
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ canvas.paint(g2);
+ }
+
+
+ int lastX, lastY;
+ int pressX, pressY;
+
+ FigureElement first = null;
+ Point point1 = null;
+
+ public void mousePressed(MouseEvent e){
+ int x = e.getX(), y = e.getY();
+ pressX = lastX = x; pressY = lastY = y;
+ first = findFigureElement(x, y);
+ if (first == null) {
+ point1 = addPoint(x, y);
+ }
+ }
+
+ public void mouseDragged(MouseEvent e) {
+ int x = e.getX(), y = e.getY(), dx = lastX-x, dy = lastY-y;
+ lastX = x;
+ lastY = y;
+ if (first == null) {
+ Line line = addLine(point1, new Point(x, y));
+ if (line != null) {
+ canvas.add(line.getP2());
+ first = line.getP2();
+ canvas.add(line);
+ }
+ } else {
+ first.move(-dx, -dy);
+ }
+ repaint();
+ }
+
+ public void mouseReleased(MouseEvent e){
+ mouseDragged(e);
+ first = null;
+ point1 = null;
+ }
+
+
+ public void mouseMoved(MouseEvent e){}
+ public void mouseClicked(MouseEvent e){}
+ public void mouseExited(MouseEvent e){}
+ public void mouseEntered(MouseEvent e){}
+
+ private FigureElement findFigureElement(int x, int y) {
+ Point2D p = new Point2D.Float((float)x, (float)y);
+ for (Iterator i = canvas.members(); i.hasNext(); ) {
+ FigureElement fe = (FigureElement)i.next();
+ if (fe.contains(p)) return fe;
+ }
+ return null;
+ }
+ }
+}
diff --git a/docs/teaching/demos/figures/src-fresh/figures/gui/LogAdapter.java b/docs/teaching/demos/figures/src-fresh/figures/gui/LogAdapter.java
new file mode 100644
index 000000000..92a192f15
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/gui/LogAdapter.java
@@ -0,0 +1,16 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures.gui;
+
+import figures.support.Log;
+
+aspect LogAdapter {
+
+ before(String s): call(void Log.log(String)) && args(s) {
+ if (Main.panel != null) {
+ Main.panel.cp.println(s);
+ }
+ }
+}
diff --git a/docs/teaching/demos/figures/src-fresh/figures/gui/Main.java b/docs/teaching/demos/figures/src-fresh/figures/gui/Main.java
new file mode 100644
index 000000000..da257aeda
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/gui/Main.java
@@ -0,0 +1,25 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures.gui;
+
+import javax.swing.*;
+import figures.support.Log;
+import figures.Point;
+
+public class Main {
+ static FigurePanel panel;
+
+ public static void main(String[] args) {
+ JFrame figureFrame = new JFrame("Figure Editor");
+ panel = new FigurePanel();
+ figureFrame.setContentPane(panel);
+ figureFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ figureFrame.pack();
+ figureFrame.setVisible(true);
+
+// Point p = new Point(0, 0);
+// p.setX(-10);
+ }
+}
diff --git a/docs/teaching/demos/figures/src-fresh/figures/support/Log.java b/docs/teaching/demos/figures/src-fresh/figures/support/Log.java
new file mode 100644
index 000000000..1ae18cc46
--- /dev/null
+++ b/docs/teaching/demos/figures/src-fresh/figures/support/Log.java
@@ -0,0 +1,36 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures.support;
+
+public class Log {
+ private static StringBuffer data = new StringBuffer();
+
+ public static void traceObject(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ public static void log(String s) {
+ data.append(s);
+ data.append(';');
+ }
+
+ public static void logClassName(Class _class) {
+ String name = _class.getName();
+ int dot = name.lastIndexOf('.');
+ if (dot == -1) {
+ log(name);
+ } else {
+ log(name.substring(dot+1, name.length()));
+ }
+ }
+
+ public static String getString() {
+ return data.toString();
+ }
+
+ public static void clear() {
+ data.setLength(0);
+ }
+}
diff --git a/docs/teaching/demos/figures/src/figures/Box.java b/docs/teaching/demos/figures/src/figures/Box.java
new file mode 100644
index 000000000..4db7f439d
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/Box.java
@@ -0,0 +1,55 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Box extends ShapeFigureElement {
+ private Point _p0;
+ private Point _p1;
+ private Point _p2;
+ private Point _p3;
+
+ public Box(int x0, int y0, int width, int height) {
+ _p0 = new Point(x0, y0);
+ _p1 = new Point(x0+width, y0);
+ _p2 = new Point(x0+width, y0+height);
+ _p3 = new Point(x0, y0+height);
+ }
+
+ public Point getP0() { return _p0; }
+ public Point getP1() { return _p1; }
+ public Point getP2() { return _p2; }
+ public Point getP3() { return _p3; }
+
+ public void move(int dx, int dy) {
+ _p0.move(dx, dy);
+ _p1.move(dx, dy);
+ _p2.move(dx, dy);
+ _p3.move(dx, dy);
+ }
+
+ public void checkBoxness() {
+ if ((_p0.getX() == _p3.getX()) &&
+ (_p1.getX() == _p2.getX()) &&
+ (_p0.getY() == _p1.getY()) &&
+ (_p2.getY() == _p3.getY()))
+ return;
+ throw new IllegalStateException("This is not a square.");
+ }
+
+ public String toString() {
+ return "Box(" + _p0 + ", " + _p1 + ", " + _p2 + ", " + _p3 + ")";
+ }
+
+ public Shape getShape() {
+ return new Rectangle(getP1().getX(),
+ getP1().getY(),
+ getP3().getX() - getP1().getX(),
+ getP3().getY() - getP1().getY());
+ }
+}
+
diff --git a/docs/teaching/demos/figures/src/figures/Canvas.java b/docs/teaching/demos/figures/src/figures/Canvas.java
new file mode 100644
index 000000000..ef849a5d5
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/Canvas.java
@@ -0,0 +1,15 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import figures.support.Log;
+
+public class Canvas {
+ public static void updateHistory() { }
+
+ public static void updateHistory(FigureElement fe) {
+ System.out.println("> updating history for: " + fe);
+ }
+}
diff --git a/docs/teaching/demos/figures/src/figures/ColorControl.java b/docs/teaching/demos/figures/src/figures/ColorControl.java
new file mode 100644
index 000000000..f1a76512b
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/ColorControl.java
@@ -0,0 +1,16 @@
+package figures;
+
+import java.awt.Color;
+import figures.FigureElement;
+
+public aspect ColorControl {
+ public static void setFillColor(FigureElement fe, Color color) {
+ // fill in here
+ }
+
+ public static void setLineColor(FigureElement fe, Color color) {
+ // fill in here
+ }
+
+ // fill in here
+}
diff --git a/docs/teaching/demos/figures/src/figures/FigureElement.java b/docs/teaching/demos/figures/src/figures/FigureElement.java
new file mode 100644
index 000000000..ae06c132b
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/FigureElement.java
@@ -0,0 +1,21 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public interface FigureElement {
+ public static final int MIN_VALUE = 0;
+ public static final int MAX_VALUE = 500;
+
+ public abstract void move(int dx, int dy);
+
+ public abstract Rectangle getBounds();
+
+ public abstract boolean contains(Point2D p);
+
+ public abstract void paint(Graphics2D g2);
+}
diff --git a/docs/teaching/demos/figures/src/figures/Group.java b/docs/teaching/demos/figures/src/figures/Group.java
new file mode 100644
index 000000000..59c1a17cf
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/Group.java
@@ -0,0 +1,88 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.util.*;
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Group implements FigureElement {
+ private Collection _members;
+ private String _identifier;
+
+ public Group(FigureElement first) {
+ this._members = new ArrayList();
+ add(first);
+ }
+
+ public void add(FigureElement fe) {
+ _members.add(fe);
+ }
+
+ public Iterator members() {
+ return _members.iterator();
+ }
+
+ public void move(int dx, int dy) {
+ for (Iterator i = _members.iterator(); i.hasNext(); ) {
+ FigureElement fe = (FigureElement)i.next();
+ fe.move(dx, dy);
+ }
+ }
+
+ public void resetIdentifier(String identifier) {
+ resetIdentifier(identifier);
+ }
+
+ public String toString() {
+ if (_identifier != null) {
+ return _identifier;
+ }
+
+ StringBuffer buf = new StringBuffer("Group(");
+ for (Iterator i = _members.iterator(); i.hasNext(); ) {
+ buf.append(i.next().toString());
+ if (i.hasNext()) {
+ buf.append(", ");
+ }
+ }
+ buf.append(")");
+ return buf.toString();
+ }
+
+ public Rectangle getBounds() {
+ Rectangle previous = null;
+ for (Iterator i = _members.iterator(); i.hasNext(); ) {
+ FigureElement fe = (FigureElement)i.next();
+ Rectangle rect = fe.getBounds();
+ if (previous != null) {
+ previous = previous.union(rect);
+ } else {
+ previous = rect;
+ }
+ }
+ return previous;
+ }
+
+ public boolean contains(Point2D p) {
+ for (Iterator i = _members.iterator(); i.hasNext(); ) {
+ FigureElement fe = (FigureElement)i.next();
+ if (fe.contains(p)) return true;
+ }
+ return false;
+ }
+
+ public void paint(Graphics2D g2) {
+ for (Iterator i = _members.iterator(); i.hasNext(); ) {
+ FigureElement fe = (FigureElement)i.next();
+ fe.paint(g2);
+ }
+ }
+
+ public int size() {
+ return _members.size();
+ }
+}
+
diff --git a/docs/teaching/demos/figures/src/figures/Line.java b/docs/teaching/demos/figures/src/figures/Line.java
new file mode 100644
index 000000000..e9911c6d7
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/Line.java
@@ -0,0 +1,70 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Line extends ShapeFigureElement {
+ private Point _p1;
+ private Point _p2;
+
+ public Line(Point p1, Point p2) {
+ _p1 = p1;
+ _p2 = p2;
+ }
+
+ public Point getP1() {
+ return _p1;
+ }
+
+ public void setP1(Point p1) {
+ _p1 = p1;
+// Canvas.updateHistory();
+ }
+
+ public Point getP2() {
+ return _p2;
+ }
+
+ public void setP2(Point p2) {
+ _p2 = p2;
+// Canvas.updateHistory();
+ }
+
+ public void move(int dx, int dy) {
+ _p1.move(dx, dy);
+ _p2.move(dx, dy);
+ }
+
+ public String toString() {
+ return "Line(" + _p1 + ", " + _p2 + ")";
+ }
+
+ /**
+ * Used to determine if this line {@link contains(Point2D)} a point.
+ */
+ final static int THRESHHOLD = 5;
+
+ /**
+ * Returns <code>true</code> if the point segment distance is less than
+ * {@link THRESHHOLD}.
+ */
+ public boolean contains(Point2D p) {
+ return getLine2D().ptLineDist(p) < THRESHHOLD;
+ }
+
+ private Line2D getLine2D() {
+ return new Line2D.Float((float)getP1().getX(),
+ (float)getP1().getY(),
+ (float)getP2().getX(),
+ (float)getP2().getY());
+ }
+
+ public Shape getShape() {
+ return getLine2D();
+ }
+}
+
diff --git a/docs/teaching/demos/figures/src/figures/Point.java b/docs/teaching/demos/figures/src/figures/Point.java
new file mode 100644
index 000000000..d832b983c
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/Point.java
@@ -0,0 +1,59 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public class Point extends ShapeFigureElement {
+ private int _x;
+ private int _y;
+
+ public Point(int x, int y) {
+ _x = x;
+ _y = y;
+ }
+
+ public int getX() {
+ return _x;
+ }
+
+ public void setX(int x) {
+ _x = x;
+// Canvas.updateHistory();
+ }
+
+ public int getY() {
+ return _y;
+ }
+
+ public void setY(int y) {
+ _y = y;
+// Canvas.updateHistory();
+ }
+
+ public void move(int dx, int dy) {
+ setX(_x + dx);
+ setY(_y + dy);
+ }
+
+ public String toString() {
+ return "Point(" + _x + ", " + _y + ")";
+ }
+
+ /** The height of displayed {@link Point}s. */
+ private final static int HEIGHT = 10;
+
+ /** The width of displayed {@link Point}s. -- same as {@link HEIGHT}. */
+ private final static int WIDTH = Point.HEIGHT;
+
+ public Shape getShape() {
+ return new Ellipse2D.Float((float)getX()-Point.WIDTH/2,
+ (float)getY()-Point.HEIGHT/2,
+ (float)Point.HEIGHT,
+ (float)Point.WIDTH);
+ }
+}
+
diff --git a/docs/teaching/demos/figures/src/figures/ShapeFigureElement.java b/docs/teaching/demos/figures/src/figures/ShapeFigureElement.java
new file mode 100644
index 000000000..29a4a89ad
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/ShapeFigureElement.java
@@ -0,0 +1,38 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+public abstract class ShapeFigureElement implements FigureElement {
+ public abstract void move(int dx, int dy);
+
+ public abstract Shape getShape();
+
+ public Rectangle getBounds() {
+ return getShape().getBounds();
+ }
+
+ public boolean contains(Point2D p) {
+ return getShape().contains(p);
+ }
+
+ public Color getLineColor() {
+ return Color.black;
+ }
+
+ public Color getFillColor() {
+ return Color.red;
+ }
+
+ public final void paint(Graphics2D g2) {
+ Shape shape = getShape();
+ g2.setPaint(getFillColor());
+ g2.fill(shape);
+ g2.setPaint(getLineColor());
+ g2.draw(shape);
+ }
+}
diff --git a/docs/teaching/demos/figures/src/figures/SlothfulPoint.java b/docs/teaching/demos/figures/src/figures/SlothfulPoint.java
new file mode 100644
index 000000000..620970373
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/SlothfulPoint.java
@@ -0,0 +1,42 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures;
+
+import java.awt.*;
+import java.awt.geom.*;
+
+/**
+ * This class makes mistakes to be caught by invariant checkers.
+ */
+public class SlothfulPoint extends ShapeFigureElement {
+ private int _x;
+ private int _y;
+
+ public SlothfulPoint(int x, int y) {
+ }
+
+ public void setX(int x) {
+ _x = x;
+ }
+
+ public void setY(int y) {
+ _y = y;
+ }
+
+ public void move(int dx, int dy) {
+ setX(_x + dx);
+ setY(_y + dy);
+ }
+
+ public String toString() {
+ return "SlothfulPoint";
+ }
+
+ public Shape getShape() {
+ return new Ellipse2D.Float((float)_x,
+ (float)_y, 1.0f, 1.0f);
+ }
+}
+
diff --git a/docs/teaching/demos/figures/src/figures/gui/FigurePanel.java b/docs/teaching/demos/figures/src/figures/gui/FigurePanel.java
new file mode 100644
index 000000000..cac59e835
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/gui/FigurePanel.java
@@ -0,0 +1,172 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures.gui;
+
+import figures.Point;
+import figures.Line;
+import figures.FigureElement;
+import figures.Group;
+
+
+import java.awt.*;
+import java.awt.geom.*;
+import java.awt.event.*;
+import java.io.*;
+import java.util.*;
+import javax.swing.*;
+import javax.swing.text.*;
+import javax.swing.border.*;
+
+public class FigurePanel extends JComponent {
+
+ ButtonsPanel bp = new ButtonsPanel();
+ FigureSurface fs = new FigureSurface();
+ ConsolePanel cp = new ConsolePanel();
+
+
+ public FigurePanel() {
+ setLayout(new BorderLayout());
+ JPanel panel = new JPanel();
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ panel.add(fs);
+ panel.add(bp);
+ JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, panel, cp);
+ sp.setPreferredSize(new Dimension(500, 400));
+ sp.setDividerLocation(250);
+ add(BorderLayout.CENTER, sp);
+ }
+
+ class ButtonsPanel extends JPanel {
+ private JLabel msgs = new JLabel("click to add a point or line");
+ public ButtonsPanel() {
+ setLayout(new FlowLayout(FlowLayout.LEFT));
+// add(new JButton(new AbstractAction("Main") {
+// public void actionPerformed(ActionEvent e) {
+// Main.main(new String[]{});
+// fs.repaint();
+// }
+// }));
+ add(msgs);
+ }
+
+ public void log(String msg) {
+ msgs.setText(msg);
+ }
+ }
+
+ static class ConsolePanel extends JPanel {
+
+ JTextArea text = new JTextArea();
+
+ public ConsolePanel() {
+ super(new BorderLayout());
+ text.setFont(StyleContext.getDefaultStyleContext().getFont("SansSerif", Font.PLAIN, 10));
+ JScrollPane scroller = new JScrollPane(text);
+ scroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
+ add(BorderLayout.CENTER, scroller);
+ }
+
+ public void println(String msg) {
+ text.append(msg + '\n');
+ }
+ }
+
+ final static Color BACKGROUND = Color.white;
+
+ static class FigureSurface extends JPanel implements MouseListener, MouseMotionListener {
+ private Group canvas;
+
+ public FigureSurface() {
+ canvas = new Group(new Point(250, 250));
+ addMouseMotionListener(this);
+ addMouseListener(this);
+ setPreferredSize(new Dimension(500,500));
+ }
+
+ private Point addPoint(int x, int y) {
+ Point p = new Point(x, y);
+ canvas.add(p);
+ repaint();
+ return p;
+ }
+
+ private Line addLine(Point p1, Point p2) {
+ if (Math.abs(p1.getX()-p2.getX()) < 5 ||
+ Math.abs(p1.getY()-p2.getY()) < 5) {
+ return null;
+ }
+
+ Line line = null;
+ if (p1 != null && p2 != null) {
+ line = new Line(p1, p2);
+ canvas.add(line);
+ }
+ repaint();
+ return line;
+ }
+
+ public void paint(Graphics g) {
+ Graphics2D g2 = (Graphics2D) g;
+ g2.setPaint(BACKGROUND);
+ g2.fill(new Rectangle2D.Float(0f, 0f, (float)g2.getClipBounds().width, (float)g2.getClipBounds().height));
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ canvas.paint(g2);
+ }
+
+
+ int lastX, lastY;
+ int pressX, pressY;
+
+ FigureElement first = null;
+ Point point1 = null;
+
+ public void mousePressed(MouseEvent e){
+ int x = e.getX(), y = e.getY();
+ pressX = lastX = x; pressY = lastY = y;
+ first = findFigureElement(x, y);
+ if (first == null) {
+ point1 = addPoint(x, y);
+ }
+ }
+
+ public void mouseDragged(MouseEvent e) {
+ int x = e.getX(), y = e.getY(), dx = lastX-x, dy = lastY-y;
+ lastX = x;
+ lastY = y;
+ if (first == null) {
+ Line line = addLine(point1, new Point(x, y));
+ if (line != null) {
+ canvas.add(line.getP2());
+ first = line.getP2();
+ canvas.add(line);
+ }
+ } else {
+ first.move(-dx, -dy);
+ }
+ repaint();
+ }
+
+ public void mouseReleased(MouseEvent e){
+ mouseDragged(e);
+ first = null;
+ point1 = null;
+ }
+
+
+ public void mouseMoved(MouseEvent e){}
+ public void mouseClicked(MouseEvent e){}
+ public void mouseExited(MouseEvent e){}
+ public void mouseEntered(MouseEvent e){}
+
+ private FigureElement findFigureElement(int x, int y) {
+ Point2D p = new Point2D.Float((float)x, (float)y);
+ for (Iterator i = canvas.members(); i.hasNext(); ) {
+ FigureElement fe = (FigureElement)i.next();
+ if (fe.contains(p)) return fe;
+ }
+ return null;
+ }
+ }
+}
diff --git a/docs/teaching/demos/figures/src/figures/gui/LogAdapter.java b/docs/teaching/demos/figures/src/figures/gui/LogAdapter.java
new file mode 100644
index 000000000..92a192f15
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/gui/LogAdapter.java
@@ -0,0 +1,16 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures.gui;
+
+import figures.support.Log;
+
+aspect LogAdapter {
+
+ before(String s): call(void Log.log(String)) && args(s) {
+ if (Main.panel != null) {
+ Main.panel.cp.println(s);
+ }
+ }
+}
diff --git a/docs/teaching/demos/figures/src/figures/gui/Main.java b/docs/teaching/demos/figures/src/figures/gui/Main.java
new file mode 100644
index 000000000..d69f903e8
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/gui/Main.java
@@ -0,0 +1,25 @@
+/*
+Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures.gui;
+
+import javax.swing.*;
+import figures.support.Log;
+import figures.Point;
+
+public class Main {
+ static FigurePanel panel;
+
+ public static void main(String[] args) {
+ JFrame figureFrame = new JFrame("Figure Editor");
+ panel = new FigurePanel();
+ figureFrame.setContentPane(panel);
+ figureFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ figureFrame.pack();
+ figureFrame.setVisible(true);
+
+ Point p = new Point(0, 0);
+ p.setX(-10);
+ }
+}
diff --git a/docs/teaching/demos/figures/src/figures/support/HistoryUpdating.aj b/docs/teaching/demos/figures/src/figures/support/HistoryUpdating.aj
new file mode 100644
index 000000000..9699d032a
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/support/HistoryUpdating.aj
@@ -0,0 +1,27 @@
+package figures.support;
+
+import figures.*;
+
+public aspect HistoryUpdating {
+
+ pointcut moves(FigureElement fe):
+ this(fe) &&
+ execution(void FigureElement+.set*(..));
+
+ after(FigureElement fe) returning: moves(fe) {
+ Canvas.updateHistory(fe);
+ }
+
+ declare error:
+ set(private * FigureElement+.*) &&
+ !(withincode(void FigureElement+.set*(..)) ||
+ withincode(FigureElement+.new(..))):
+ "doh!!!";
+
+ before(int newValue):
+ set(int Point.*) && args(newValue) {
+ if (newValue < 0) {
+ throw new IllegalArgumentException("too small");
+ }
+ }
+}
diff --git a/docs/teaching/demos/figures/src/figures/support/Log.java b/docs/teaching/demos/figures/src/figures/support/Log.java
new file mode 100644
index 000000000..1ae18cc46
--- /dev/null
+++ b/docs/teaching/demos/figures/src/figures/support/Log.java
@@ -0,0 +1,36 @@
+/*
+Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved.
+ */
+
+package figures.support;
+
+public class Log {
+ private static StringBuffer data = new StringBuffer();
+
+ public static void traceObject(Object o) {
+ throw new UnsupportedOperationException();
+ }
+
+ public static void log(String s) {
+ data.append(s);
+ data.append(';');
+ }
+
+ public static void logClassName(Class _class) {
+ String name = _class.getName();
+ int dot = name.lastIndexOf('.');
+ if (dot == -1) {
+ log(name);
+ } else {
+ log(name.substring(dot+1, name.length()));
+ }
+ }
+
+ public static String getString() {
+ return data.toString();
+ }
+
+ public static void clear() {
+ data.setLength(0);
+ }
+}