commit c60769b7a3c6d1478c259a4a62f290fc4d26339f Author: Sean Hickey Date: Sun Jul 15 00:48:06 2012 -0400 committing everything FIRST POST diff --git a/AndroidManifest.xml b/AndroidManifest.xml new file mode 100644 index 0000000..12d460b --- /dev/null +++ b/AndroidManifest.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/README b/README new file mode 100644 index 0000000..1113c42 --- /dev/null +++ b/README @@ -0,0 +1 @@ +This is a very simple drawing app that just displays a square everywhere you drag your finger. That's it. \ No newline at end of file diff --git a/bin/SimpleDrawingApp.apk b/bin/SimpleDrawingApp.apk new file mode 100644 index 0000000..1629f7e Binary files /dev/null and b/bin/SimpleDrawingApp.apk differ diff --git a/bin/classes.dex b/bin/classes.dex new file mode 100644 index 0000000..1220645 Binary files /dev/null and b/bin/classes.dex differ diff --git a/bin/classes/com/SimpleDrawingApp/BuildConfig.class b/bin/classes/com/SimpleDrawingApp/BuildConfig.class new file mode 100644 index 0000000..6e99a03 Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/BuildConfig.class differ diff --git a/bin/classes/com/SimpleDrawingApp/FirstAppSurfaceView.class b/bin/classes/com/SimpleDrawingApp/FirstAppSurfaceView.class new file mode 100644 index 0000000..b516da5 Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/FirstAppSurfaceView.class differ diff --git a/bin/classes/com/SimpleDrawingApp/R$attr.class b/bin/classes/com/SimpleDrawingApp/R$attr.class new file mode 100644 index 0000000..0cd43ac Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/R$attr.class differ diff --git a/bin/classes/com/SimpleDrawingApp/R$drawable.class b/bin/classes/com/SimpleDrawingApp/R$drawable.class new file mode 100644 index 0000000..c2606dc Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/R$drawable.class differ diff --git a/bin/classes/com/SimpleDrawingApp/R$layout.class b/bin/classes/com/SimpleDrawingApp/R$layout.class new file mode 100644 index 0000000..be88837 Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/R$layout.class differ diff --git a/bin/classes/com/SimpleDrawingApp/R$string.class b/bin/classes/com/SimpleDrawingApp/R$string.class new file mode 100644 index 0000000..b58ae3d Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/R$string.class differ diff --git a/bin/classes/com/SimpleDrawingApp/R.class b/bin/classes/com/SimpleDrawingApp/R.class new file mode 100644 index 0000000..9b9c51b Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/R.class differ diff --git a/bin/classes/com/SimpleDrawingApp/SimpleDrawingAppActivity.class b/bin/classes/com/SimpleDrawingApp/SimpleDrawingAppActivity.class new file mode 100644 index 0000000..c90779d Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/SimpleDrawingAppActivity.class differ diff --git a/bin/classes/com/SimpleDrawingApp/SimpleDrawingAppRenderer.class b/bin/classes/com/SimpleDrawingApp/SimpleDrawingAppRenderer.class new file mode 100644 index 0000000..54e18f5 Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/SimpleDrawingAppRenderer.class differ diff --git a/bin/classes/com/SimpleDrawingApp/Square.class b/bin/classes/com/SimpleDrawingApp/Square.class new file mode 100644 index 0000000..06edd74 Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/Square.class differ diff --git a/bin/classes/com/SimpleDrawingApp/list/DList.class b/bin/classes/com/SimpleDrawingApp/list/DList.class new file mode 100644 index 0000000..83db77a Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/list/DList.class differ diff --git a/bin/classes/com/SimpleDrawingApp/list/DListNode.class b/bin/classes/com/SimpleDrawingApp/list/DListNode.class new file mode 100644 index 0000000..cf936ec Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/list/DListNode.class differ diff --git a/bin/classes/com/SimpleDrawingApp/list/InvalidNodeException.class b/bin/classes/com/SimpleDrawingApp/list/InvalidNodeException.class new file mode 100644 index 0000000..b55d33c Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/list/InvalidNodeException.class differ diff --git a/bin/classes/com/SimpleDrawingApp/list/List.class b/bin/classes/com/SimpleDrawingApp/list/List.class new file mode 100644 index 0000000..34a8565 Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/list/List.class differ diff --git a/bin/classes/com/SimpleDrawingApp/list/ListNode.class b/bin/classes/com/SimpleDrawingApp/list/ListNode.class new file mode 100644 index 0000000..687f3f0 Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/list/ListNode.class differ diff --git a/bin/classes/com/SimpleDrawingApp/list/SList.class b/bin/classes/com/SimpleDrawingApp/list/SList.class new file mode 100644 index 0000000..9361869 Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/list/SList.class differ diff --git a/bin/classes/com/SimpleDrawingApp/list/SListNode.class b/bin/classes/com/SimpleDrawingApp/list/SListNode.class new file mode 100644 index 0000000..f2529fe Binary files /dev/null and b/bin/classes/com/SimpleDrawingApp/list/SListNode.class differ diff --git a/bin/jarlist.cache b/bin/jarlist.cache new file mode 100644 index 0000000..1b5ec3f --- /dev/null +++ b/bin/jarlist.cache @@ -0,0 +1,3 @@ +# cache for current jar dependecy. DO NOT EDIT. +# format is +# Encoding is UTF-8 diff --git a/bin/res/drawable-hdpi/ic_launcher.png b/bin/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..bcfa058 Binary files /dev/null and b/bin/res/drawable-hdpi/ic_launcher.png differ diff --git a/bin/res/drawable-ldpi/ic_launcher.png b/bin/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000..dd7c05b Binary files /dev/null and b/bin/res/drawable-ldpi/ic_launcher.png differ diff --git a/bin/res/drawable-mdpi/ic_launcher.png b/bin/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..85848ff Binary files /dev/null and b/bin/res/drawable-mdpi/ic_launcher.png differ diff --git a/bin/res/drawable-xhdpi/ic_launcher.png b/bin/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..916901e Binary files /dev/null and b/bin/res/drawable-xhdpi/ic_launcher.png differ diff --git a/bin/resources.ap_ b/bin/resources.ap_ new file mode 100644 index 0000000..a512314 Binary files /dev/null and b/bin/resources.ap_ differ diff --git a/gen/com/SimpleDrawingApp/BuildConfig.java b/gen/com/SimpleDrawingApp/BuildConfig.java new file mode 100644 index 0000000..66d9de5 --- /dev/null +++ b/gen/com/SimpleDrawingApp/BuildConfig.java @@ -0,0 +1,6 @@ +/** Automatically generated file. DO NOT MODIFY */ +package com.SimpleDrawingApp; + +public final class BuildConfig { + public final static boolean DEBUG = true; +} \ No newline at end of file diff --git a/gen/com/SimpleDrawingApp/R.java b/gen/com/SimpleDrawingApp/R.java new file mode 100644 index 0000000..ad908e5 --- /dev/null +++ b/gen/com/SimpleDrawingApp/R.java @@ -0,0 +1,23 @@ +/* AUTO-GENERATED FILE. DO NOT MODIFY. + * + * This class was automatically generated by the + * aapt tool from the resource data it found. It + * should not be modified by hand. + */ + +package com.SimpleDrawingApp; + +public final class R { + public static final class attr { + } + public static final class drawable { + public static final int ic_launcher=0x7f020000; + } + public static final class layout { + public static final int main=0x7f030000; + } + public static final class string { + public static final int app_name=0x7f040001; + public static final int hello=0x7f040000; + } +} diff --git a/proguard-project.txt b/proguard-project.txt new file mode 100644 index 0000000..f2fe155 --- /dev/null +++ b/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/project.properties b/project.properties new file mode 100644 index 0000000..22d0dca --- /dev/null +++ b/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-7 diff --git a/res/drawable-hdpi/ic_launcher.png b/res/drawable-hdpi/ic_launcher.png new file mode 100644 index 0000000..96a442e Binary files /dev/null and b/res/drawable-hdpi/ic_launcher.png differ diff --git a/res/drawable-ldpi/ic_launcher.png b/res/drawable-ldpi/ic_launcher.png new file mode 100644 index 0000000..9923872 Binary files /dev/null and b/res/drawable-ldpi/ic_launcher.png differ diff --git a/res/drawable-mdpi/ic_launcher.png b/res/drawable-mdpi/ic_launcher.png new file mode 100644 index 0000000..359047d Binary files /dev/null and b/res/drawable-mdpi/ic_launcher.png differ diff --git a/res/drawable-xhdpi/ic_launcher.png b/res/drawable-xhdpi/ic_launcher.png new file mode 100644 index 0000000..71c6d76 Binary files /dev/null and b/res/drawable-xhdpi/ic_launcher.png differ diff --git a/res/layout/main.xml b/res/layout/main.xml new file mode 100644 index 0000000..bc12cd8 --- /dev/null +++ b/res/layout/main.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml new file mode 100644 index 0000000..0caa708 --- /dev/null +++ b/res/values/strings.xml @@ -0,0 +1,7 @@ + + + + Hello World, SimpleDrawingAppActivity! + SimpleDrawingApp + + \ No newline at end of file diff --git a/src/com/SimpleDrawingApp/SimpleDrawingAppActivity.java b/src/com/SimpleDrawingApp/SimpleDrawingAppActivity.java new file mode 100644 index 0000000..d33fa73 --- /dev/null +++ b/src/com/SimpleDrawingApp/SimpleDrawingAppActivity.java @@ -0,0 +1,94 @@ +package com.SimpleDrawingApp; + +import android.app.Activity; +//import android.content.Intent; +import android.content.Context; +import android.os.Bundle; +//import android.view.View; +import android.view.MotionEvent; +import android.opengl.GLSurfaceView; +//import android.widget.EditText; + +public class SimpleDrawingAppActivity extends Activity { + /** Called when the activity is first created. */ + public final static String EXTRA_MESSAGE = "firstApp.main.MESSAGE"; + private GLSurfaceView mGLView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // setContentView(R.layout.main); + mGLView = new FirstAppSurfaceView(this); + setContentView(mGLView); + } + + @Override + protected void onPause() { + super.onPause(); + mGLView.onPause(); + } + + @Override + protected void onResume() { + super.onResume(); + mGLView.onResume(); + } + + /*public void sendMessage(View view) { + Intent intent = new Intent(this, DisplayMessageActivity.class); + EditText editText = (EditText) findViewById(R.id.edit_message); + String message = editText.getText().toString(); + intent.putExtra(EXTRA_MESSAGE, message); + startActivity(intent); + }*/ +} + +class FirstAppSurfaceView extends GLSurfaceView { + private final float X_SCALE_FACTOR = 1f / (240); // determined through trial + // and error + private final float Y_SCALE_FACTOR = 1f / (240); + private SimpleDrawingAppRenderer mRenderer; + private float mPreviousX; + private float mPreviousY; + + public FirstAppSurfaceView(Context context) { + super(context); + + mRenderer = new SimpleDrawingAppRenderer(); + setRenderer(mRenderer); + setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); + } + + @Override + public boolean onTouchEvent(MotionEvent e) { + float x = e.getX(); + float y = e.getY(); + + float dx = 0; + float dy = 0; + + switch (e.getAction()) { + case MotionEvent.ACTION_MOVE: + dx = x - mPreviousX; + dx *= -1; + mRenderer.xPosition = x*X_SCALE_FACTOR*-1 + 1; + mRenderer.dx = dx*X_SCALE_FACTOR; + + dy = y - mPreviousY; + dy *= -1; + mRenderer.yPosition = y*Y_SCALE_FACTOR*-1 + 1.6f; + mRenderer.dy = dy * Y_SCALE_FACTOR; + + Square s = new Square(x*X_SCALE_FACTOR*-1 + .975f, y*Y_SCALE_FACTOR*-1 + 1.5f); + mRenderer.squareList.insertBack(s); + + requestRender(); + break; + + } + + mPreviousX = x; + mPreviousY = y; + return true; + } +} \ No newline at end of file diff --git a/src/com/SimpleDrawingApp/SimpleDrawingAppRenderer.java b/src/com/SimpleDrawingApp/SimpleDrawingAppRenderer.java new file mode 100644 index 0000000..96b08d2 --- /dev/null +++ b/src/com/SimpleDrawingApp/SimpleDrawingAppRenderer.java @@ -0,0 +1,56 @@ +package com.SimpleDrawingApp; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import android.opengl.GLSurfaceView; +import android.opengl.GLU; + +import com.SimpleDrawingApp.list.*; + +public class SimpleDrawingAppRenderer implements GLSurfaceView.Renderer { + public DList squareList = new DList(); + public float xPosition, dx; + public float yPosition, dy; + + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + gl.glClearColor(0f, 0f, 0f, 1.0f); + } + + public void onDrawFrame(GL10 gl) { + gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); + gl.glMatrixMode(GL10.GL_MODELVIEW); + gl.glLoadIdentity(); + GLU.gluLookAt(gl, 0, 0, -5, 0f, 0f, 0f, 0f, 1.0f, 0.0f); + + try { + ListNode currentNode = squareList.front(); + while(currentNode.isValidNode()) { + Square s = (Square)currentNode.item(); + s.Draw(gl); + + currentNode = currentNode.next(); + } + } + catch (InvalidNodeException e) { + System.err.println(e + "in onDrawFrame"); + } + + } + + public void onSurfaceChanged(GL10 gl, int width, int height) { + gl.glViewport(0, 0, width, height); + + float ratio = (float) width / height; + gl.glMatrixMode(GL10.GL_PROJECTION); // set matrix to projection mode + gl.glLoadIdentity(); // reset the matrix to its default state + gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7); // apply the projection + // matrix + + initShapes(); + gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); + } + + private void initShapes() { + } +} \ No newline at end of file diff --git a/src/com/SimpleDrawingApp/Square.java b/src/com/SimpleDrawingApp/Square.java new file mode 100644 index 0000000..1dcaea8 --- /dev/null +++ b/src/com/SimpleDrawingApp/Square.java @@ -0,0 +1,54 @@ +package com.SimpleDrawingApp; + +import java.nio.*; + +import javax.microedition.khronos.opengles.GL10; + +class Square { + + private FloatBuffer squareVB, squareVB2; + + static float squareCoords[] = { -0.1f, 0.1f, 0.0f, // top left + -0.1f, -0.1f, 0.0f, // bottom left + 0.1f, -0.1f, 0.0f}; // bottom right + + static float square2Coords[] = { -0.1f, 0.1f, 0.0f, // top left + 0.1f, -0.1f, 0.0f, // bottom right + 0.1f, 0.1f, 0.0f }; // top right + private float x,y; + + public Square() { + + x = 0; + y = 0; + + ByteBuffer vbb = ByteBuffer.allocateDirect(squareCoords.length * 4); + vbb.order(ByteOrder.nativeOrder()); + squareVB = vbb.asFloatBuffer(); + squareVB.put(squareCoords); + squareVB.position(0); + + ByteBuffer vbb2 = ByteBuffer.allocateDirect(square2Coords.length * 4); + vbb2.order(ByteOrder.nativeOrder()); + squareVB2 = vbb2.asFloatBuffer(); + squareVB2.put(square2Coords); + squareVB2.position(0); + } + + public Square(float x, float y) { + this(); + this.x = x; + this.y = y; + } + + public void Draw(GL10 gl) { + gl.glPushMatrix(); + gl.glTranslatef(this.x,this.y,0); + gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + gl.glVertexPointer(3, GL10.GL_FLOAT, 0, squareVB); + gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3); + gl.glVertexPointer(3, GL10.GL_FLOAT, 0, squareVB2); + gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3); + gl.glPopMatrix(); + } +} \ No newline at end of file diff --git a/src/com/SimpleDrawingApp/list/DList.class b/src/com/SimpleDrawingApp/list/DList.class new file mode 100644 index 0000000..350f3a9 Binary files /dev/null and b/src/com/SimpleDrawingApp/list/DList.class differ diff --git a/src/com/SimpleDrawingApp/list/DList.java b/src/com/SimpleDrawingApp/list/DList.java new file mode 100644 index 0000000..1a46acc --- /dev/null +++ b/src/com/SimpleDrawingApp/list/DList.java @@ -0,0 +1,280 @@ +/* DList.java */ + +package com.SimpleDrawingApp.list; + +/** + * A DList is a mutable doubly-linked list ADT. Its implementation is + * circularly-linked and employs a sentinel node at the head of the list. + * + * DO NOT CHANGE ANY METHOD PROTOTYPES IN THIS FILE. + **/ + +public class DList extends List { + + /** + * (inherited) size is the number of items in the list. + * head references the sentinel node. + * Note that the sentinel node does not store an item, and is not included + * in the count stored by the "size" field. + * + * DO NOT CHANGE THE FOLLOWING FIELD DECLARATION. + **/ + + protected DListNode head; + + /* DList invariants: + * 1) head != null. + * 2) For every DListNode x in a DList, x.next != null. + * 3) For every DListNode x in a DList, x.prev != null. + * 4) For every DListNode x in a DList, if x.next == y, then y.prev == x. + * 5) For every DListNode x in a DList, if x.prev == y, then y.next == x. + * 6) For every DList l, l.head.myList = null. (Note that l.head is the + * sentinel.) + * 7) For every DListNode x in a DList l EXCEPT l.head (the sentinel), + * x.myList = l. + * 8) size is the number of DListNodes, NOT COUNTING the sentinel, + * that can be accessed from the sentinel (head) by a sequence of + * "next" references. + **/ + + /** + * newNode() calls the DListNode constructor. Use this method to allocate + * new DListNodes rather than calling the DListNode constructor directly. + * That way, only this method need be overridden if a subclass of DList + * wants to use a different kind of node. + * + * @param item the item to store in the node. + * @param list the list that owns this node. (null for sentinels.) + * @param prev the node previous to this node. + * @param next the node following this node. + **/ + protected DListNode newNode(Object item, DList list, + DListNode prev, DListNode next) { + return new DListNode(item, list, prev, next); + } + + /** + * DList() constructs for an empty DList. + **/ + public DList() { + // Your solution here. Similar to Homework 4, but now you need to specify + // the `list' field (second parameter) as well. + head = newNode(null,this,null,null); + head.next = head; + head.prev = head; + head.myList = null; //not a valid node + size = 0; + } + + /** + * insertFront() inserts an item at the front of this DList. + * + * @param item is the item to be inserted. + * + * Performance: runs in O(1) time. + **/ + public void insertFront(Object item) { + // Your solution here. Similar to Homework 4, but now you need to specify + // the `list' field (second parameter) as well. + DListNode newNode = newNode(item,this,head,head.next); + head.next = newNode; + newNode.next.prev = newNode; + size++; + } + + /** + * insertBack() inserts an item at the back of this DList. + * + * @param item is the item to be inserted. + * + * Performance: runs in O(1) time. + **/ + public void insertBack(Object item) { + // Your solution here. Similar to Homework 4, but now you need to specify + // the `list' field (second parameter) as well. + DListNode newNode = newNode(item,this,head.prev,head); + head.prev = newNode; + newNode.prev.next = newNode; + size++; + } + + /** + * front() returns the node at the front of this DList. If the DList is + * empty, return an "invalid" node--a node with the property that any + * attempt to use it will cause an exception. (The sentinel is "invalid".) + * + * DO NOT CHANGE THIS METHOD. + * + * @return a ListNode at the front of this DList. + * + * Performance: runs in O(1) time. + */ + public ListNode front() { + return head.next; + } + + /** + * back() returns the node at the back of this DList. If the DList is + * empty, return an "invalid" node--a node with the property that any + * attempt to use it will cause an exception. (The sentinel is "invalid".) + * + * DO NOT CHANGE THIS METHOD. + * + * @return a ListNode at the back of this DList. + * + * Performance: runs in O(1) time. + */ + public ListNode back() { + return head.prev; + } + + //added by me, not from class + public void concat(List s) { + ListNode currentNode = s.front(); + try { + while(currentNode.isValidNode()) { + this.insertBack(currentNode.item()); + currentNode = currentNode.next(); + } + } + catch(InvalidNodeException e) { + System.err.println(e); + } + } + + /** + * toString() returns a String representation of this DList. + * + * DO NOT CHANGE THIS METHOD. + * + * @return a String representation of this DList. + * + * Performance: runs in O(n) time, where n is the length of the list. + */ + public String toString() { + String result = "[ "; + DListNode current = head.next; + while (current != head) { + result = result + current.item + " "; + current = current.next; + } + return result + "]"; + } + + private static void testInvalidNode(ListNode p) { + System.out.println("p.isValidNode() should be false: " + p.isValidNode()); + try { + p.item(); + System.out.println("p.item() should throw an exception, but didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.item() should throw an exception, and did."); + } + try { + p.setItem(new Integer(0)); + System.out.println("p.setItem() should throw an exception, but didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.setItem() should throw an exception, and did."); + } + try { + p.next(); + System.out.println("p.next() should throw an exception, but didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.next() should throw an exception, and did."); + } + try { + p.prev(); + System.out.println("p.prev() should throw an exception, but didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.prev() should throw an exception, and did."); + } + try { + p.insertBefore(new Integer(1)); + System.out.println("p.insertBefore() should throw an exception, but " + + "didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.insertBefore() should throw an exception, and did." + ); + } + try { + p.insertAfter(new Integer(1)); + System.out.println("p.insertAfter() should throw an exception, but " + + "didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.insertAfter() should throw an exception, and did." + ); + } + try { + p.remove(); + System.out.println("p.remove() should throw an exception, but didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.remove() should throw an exception, and did."); + } + } + + private static void testEmpty() { + List l = new DList(); + System.out.println("An empty list should be [ ]: " + l); + System.out.println("l.isEmpty() should be true: " + l.isEmpty()); + System.out.println("l.length() should be 0: " + l.length()); + System.out.println("Finding front node p of l."); + ListNode p = l.front(); + testInvalidNode(p); + System.out.println("Finding back node p of l."); + p = l.back(); + testInvalidNode(p); + l.insertFront(new Integer(10)); + System.out.println("l after insertFront(10) should be [ 10 ]: " + l); + } + + public static void main(String[] argv) { + testEmpty(); + List l = new DList(); + l.insertFront(new Integer(3)); + l.insertFront(new Integer(2)); + l.insertFront(new Integer(1)); + System.out.println("l is a list of 3 elements: " + l); + try { + ListNode n; + int i = 1; + for (n = l.front(); n.isValidNode(); n = n.next()) { + System.out.println("n.item() should be " + i + ": " + n.item()); + n.setItem(new Integer(((Integer) n.item()).intValue() * 2)); + System.out.println("n.item() should be " + 2 * i + ": " + n.item()); + i++; + } + System.out.println("After doubling all elements of l: " + l); + testInvalidNode(n); + + i = 6; + for (n = l.back(); n.isValidNode(); n = n.prev()) { + System.out.println("n.item() should be " + i + ": " + n.item()); + n.setItem(new Integer(((Integer) n.item()).intValue() * 2)); + System.out.println("n.item() should be " + 2 * i + ": " + n.item()); + i = i - 2; + } + System.out.println("After doubling all elements of l again: " + l); + testInvalidNode(n); + + n = l.front().next(); + System.out.println("Removing middle element (8) of l: " + n.item()); + n.remove(); + System.out.println("l is now: " + l); + testInvalidNode(n); + n = l.back(); + System.out.println("Removing end element (12) of l: " + n.item()); + n.remove(); + System.out.println("l is now: " + l); + testInvalidNode(n); + + n = l.front(); + System.out.println("Removing first element (4) of l: " + n.item()); + n.remove(); + System.out.println("l is now: " + l); + testInvalidNode(n); + } catch (InvalidNodeException lbe) { + System.err.println ("Caught InvalidNodeException that should not happen." + ); + System.err.println ("Aborting the testing code."); + } + } +} diff --git a/src/com/SimpleDrawingApp/list/DListNode.class b/src/com/SimpleDrawingApp/list/DListNode.class new file mode 100644 index 0000000..11021bd Binary files /dev/null and b/src/com/SimpleDrawingApp/list/DListNode.class differ diff --git a/src/com/SimpleDrawingApp/list/DListNode.java b/src/com/SimpleDrawingApp/list/DListNode.java new file mode 100644 index 0000000..5d43406 --- /dev/null +++ b/src/com/SimpleDrawingApp/list/DListNode.java @@ -0,0 +1,160 @@ +/* DListNode.java */ + +package com.SimpleDrawingApp.list; + +/** + * A DListNode is a mutable node in a DList (doubly-linked list). + **/ + +public class DListNode extends ListNode { + + /** + * (inherited) item references the item stored in the current node. + * (inherited) myList references the List that contains this node. + * prev references the previous node in the DList. + * next references the next node in the DList. + * + * DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS. + **/ + + protected DListNode prev; + protected DListNode next; + + /** + * DListNode() constructor. + * @param i the item to store in the node. + * @param l the list this node is in. + * @param p the node previous to this node. + * @param n the node following this node. + */ + DListNode(Object i, DList l, DListNode p, DListNode n) { + item = i; + myList = l; + prev = p; + next = n; + } + + /** + * isValidNode returns true if this node is valid; false otherwise. + * An invalid node is represented by a `myList' field with the value null. + * Sentinel nodes are invalid, and nodes that don't belong to a list are + * also invalid. + * + * @return true if this node is valid; false otherwise. + * + * Performance: runs in O(1) time. + */ + public boolean isValidNode() { + return myList != null; + } + + /** + * next() returns the node following this node. If this node is invalid, + * throws an exception. + * + * @return the node following this node. + * @exception InvalidNodeException if this node is not valid. + * + * Performance: runs in O(1) time. + */ + public ListNode next() throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException("next() called on invalid node"); + } + return next; + } + + /** + * prev() returns the node preceding this node. If this node is invalid, + * throws an exception. + * + * @param node the node whose predecessor is sought. + * @return the node preceding this node. + * @exception InvalidNodeException if this node is not valid. + * + * Performance: runs in O(1) time. + */ + public ListNode prev() throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException("prev() called on invalid node"); + } + return prev; + } + + /** + * insertAfter() inserts an item immediately following this node. If this + * node is invalid, throws an exception. + * + * @param item the item to be inserted. + * @exception InvalidNodeException if this node is not valid. + * + * Performance: runs in O(1) time. + */ + public void insertAfter(Object item) throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException("insertAfter() called on invalid node"); + } + // Your solution here. Will look something like your Homework 4 solution, + // but changes are necessary. For instance, there is no need to check if + // "this" is null. Remember that this node's "myList" field tells you + // what DList it's in. You should use myList.newNode() to create the + // new node. + DListNode newNode = ((DList)myList).newNode(item,(DList)myList,this,this.next); + this.next.prev = newNode; + this.next = newNode; + myList.size++; + } + + /** + * insertBefore() inserts an item immediately preceding this node. If this + * node is invalid, throws an exception. + * + * @param item the item to be inserted. + * @exception InvalidNodeException if this node is not valid. + * + * Performance: runs in O(1) time. + */ + public void insertBefore(Object item) throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException("insertBefore() called on invalid node"); + } + // Your solution here. Will look something like your Homework 4 solution, + // but changes are necessary. For instance, there is no need to check if + // "this" is null. Remember that this node's "myList" field tells you + // what DList it's in. You should use myList.newNode() to create the + // new node. + DListNode newNode = ((DList)myList).newNode(item,(DList)myList,this.prev,this); + this.prev.next = newNode; + this.prev = newNode; + myList.size++; + } + + /** + * remove() removes this node from its DList. If this node is invalid, + * throws an exception. + * + * @exception InvalidNodeException if this node is not valid. + * + * Performance: runs in O(1) time. + */ + public void remove() throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException("remove() called on invalid node"); + } + // Your solution here. Will look something like your Homework 4 solution, + // but changes are necessary. For instance, there is no need to check if + // "this" is null. Remember that this node's "myList" field tells you + // what DList it's in. + this.prev.next = this.next; + this.next.prev = this.prev; + myList.size--; + + + // Make this node an invalid node, so it cannot be used to corrupt myList. + myList = null; + // Set other references to null to improve garbage collection. + next = null; + prev = null; + } + +} diff --git a/src/com/SimpleDrawingApp/list/InvalidNodeException.class b/src/com/SimpleDrawingApp/list/InvalidNodeException.class new file mode 100644 index 0000000..09be6ce Binary files /dev/null and b/src/com/SimpleDrawingApp/list/InvalidNodeException.class differ diff --git a/src/com/SimpleDrawingApp/list/InvalidNodeException.java b/src/com/SimpleDrawingApp/list/InvalidNodeException.java new file mode 100644 index 0000000..010f63e --- /dev/null +++ b/src/com/SimpleDrawingApp/list/InvalidNodeException.java @@ -0,0 +1,19 @@ +/* InvalidNodeException.java */ + +package com.SimpleDrawingApp.list; + +/** + * Implements an Exception that signals an attempt to use an invalid ListNode. + */ + +public class InvalidNodeException extends Exception { + private static final long serialVersionUID = 1L; //eclipse complained... + + protected InvalidNodeException() { + super(); + } + + protected InvalidNodeException(String s) { + super(s); + } +} diff --git a/src/com/SimpleDrawingApp/list/List.class b/src/com/SimpleDrawingApp/list/List.class new file mode 100644 index 0000000..250d2b8 Binary files /dev/null and b/src/com/SimpleDrawingApp/list/List.class differ diff --git a/src/com/SimpleDrawingApp/list/List.java b/src/com/SimpleDrawingApp/list/List.java new file mode 100644 index 0000000..33de83d --- /dev/null +++ b/src/com/SimpleDrawingApp/list/List.java @@ -0,0 +1,80 @@ +/* List.java */ + +package com.SimpleDrawingApp.list; + +/** + * A List is a mutable list ADT. No implementation is provided. + * + * DO NOT CHANGE THIS FILE. + **/ + +public abstract class List { + + /** + * size is the number of items in the list. + **/ + + protected int size; + + /** + * isEmpty() returns true if this List is empty, false otherwise. + * + * @return true if this List is empty, false otherwise. + * + * Performance: runs in O(1) time. + **/ + public boolean isEmpty() { + return size == 0; + } + + /** + * length() returns the length of this List. + * + * @return the length of this List. + * + * Performance: runs in O(1) time. + **/ + public int length() { + return size; + } + + /** + * insertFront() inserts an item at the front of this List. + * + * @param item is the item to be inserted. + **/ + public abstract void insertFront(Object item); + + /** + * insertBack() inserts an item at the back of this List. + * + * @param item is the item to be inserted. + **/ + public abstract void insertBack(Object item); + + /** + * front() returns the node at the front of this List. If the List is + * empty, return an "invalid" node--a node with the property that any + * attempt to use it will cause an exception. + * + * @return a ListNode at the front of this List. + */ + public abstract ListNode front(); + + /** + * back() returns the node at the back of this List. If the List is + * empty, return an "invalid" node--a node with the property that any + * attempt to use it will cause an exception. + * + * @return a ListNode at the back of this List. + */ + public abstract ListNode back(); + + /** + * toString() returns a String representation of this List. + * + * @return a String representation of this List. + */ + public abstract String toString(); + +} diff --git a/src/com/SimpleDrawingApp/list/ListNode.class b/src/com/SimpleDrawingApp/list/ListNode.class new file mode 100644 index 0000000..0d141d5 Binary files /dev/null and b/src/com/SimpleDrawingApp/list/ListNode.class differ diff --git a/src/com/SimpleDrawingApp/list/ListNode.java b/src/com/SimpleDrawingApp/list/ListNode.java new file mode 100644 index 0000000..3951557 --- /dev/null +++ b/src/com/SimpleDrawingApp/list/ListNode.java @@ -0,0 +1,109 @@ +/* ListNode.java */ + +package com.SimpleDrawingApp.list; + +/** + * A ListNode is a mutable node in a list. No implementation is provided. + * + * DO NOT CHANGE THIS FILE. + **/ + +public abstract class ListNode { + + /** + * item references the item stored in the current node. + * myList references the List that contains this node. + * + * DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS. + */ + + protected Object item; + protected List myList; + + /** + * isValidNode returns true if this node is valid; false otherwise. + * By default, an invalid node is one that doesn't belong to a list (myList + * is null), but subclasses can override this definition. + * + * @return true if this node is valid; false otherwise. + * + * Performance: runs in O(1) time. + */ + public boolean isValidNode() { + return myList != null; + } + + /** + * item() returns this node's item. If this node is invalid, + * throws an exception. + * + * @return the item stored in this node. + * + * Performance: runs in O(1) time. + */ + public Object item() throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException(); + } + return item; + } + + /** + * setItem() sets this node's item to "item". If this node is invalid, + * throws an exception. + * + * Performance: runs in O(1) time. + */ + public void setItem(Object item) throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException(); + } + this.item = item; + } + + /** + * next() returns the node following this node. If this node is invalid, + * throws an exception. + * + * @return the node following this node. + * @exception InvalidNodeException if this node is not valid. + */ + public abstract ListNode next() throws InvalidNodeException; + + /** + * prev() returns the node preceding this node. If this node is invalid, + * throws an exception. + * + * @param node the node whose predecessor is sought. + * @return the node preceding this node. + * @exception InvalidNodeException if this node is not valid. + */ + public abstract ListNode prev() throws InvalidNodeException; + + /** + * insertAfter() inserts an item immediately following this node. If this + * node is invalid, throws an exception. + * + * @param item the item to be inserted. + * @exception InvalidNodeException if this node is not valid. + */ + public abstract void insertAfter(Object item) throws InvalidNodeException; + + /** + * insertBefore() inserts an item immediately preceding this node. If this + * node is invalid, throws an exception. + * + * @param item the item to be inserted. + * @exception InvalidNodeException if this node is not valid. + */ + public abstract void insertBefore(Object item) throws InvalidNodeException; + + /** + * remove() removes this node from its List. If this node is invalid, + * throws an exception. + * + * @exception InvalidNodeException if this node is not valid. + */ + public abstract void remove() throws InvalidNodeException; + +} diff --git a/src/com/SimpleDrawingApp/list/SList.class b/src/com/SimpleDrawingApp/list/SList.class new file mode 100644 index 0000000..a2be36d Binary files /dev/null and b/src/com/SimpleDrawingApp/list/SList.class differ diff --git a/src/com/SimpleDrawingApp/list/SList.java b/src/com/SimpleDrawingApp/list/SList.java new file mode 100644 index 0000000..48554e7 --- /dev/null +++ b/src/com/SimpleDrawingApp/list/SList.java @@ -0,0 +1,261 @@ +/* SList.java */ + +package com.SimpleDrawingApp.list; + +/** + * A SList is a mutable singly-linked list ADT. Its implementation employs + * a tail reference. + * + * DO NOT CHANGE THIS FILE. + **/ + +public class SList extends List { + + /** + * (inherited) size is the number of items in the list. + * head references the first node. + * tail references the last node. + **/ + + protected SListNode head; + protected SListNode tail; + + /* SList invariants: + * 1) Either head == null and tail == null, or tail.next == null and the + * SListNode referenced by tail can be reached from the head by a + * sequence of zero or more "next" references. This implies that the + * list is not circularly linked. + * 2) The "size" field is the number of SListNodes that can be accessed + * from head (including head itself) by a sequence of "next" references. + * 3) For every SListNode x in an SList l, x.myList = l. + **/ + + /** + * newNode() calls the SListNode constructor. Use this method to allocate + * new SListNodes rather than calling the SListNode constructor directly. + * That way, only this method need be overridden if a subclass of SList + * wants to use a different kind of node. + * + * @param item the item to store in the node. + * @param next the node following this node. + **/ + protected SListNode newNode(Object item, SListNode next) { + return new SListNode(item, this, next); + } + + /** + * SList() constructs for an empty SList. + **/ + public SList() { + head = null; + tail = null; + size = 0; + } + + /** + * insertFront() inserts an item at the front of this SList. + * + * @param item is the item to be inserted. + * + * Performance: runs in O(1) time. + **/ + public void insertFront(Object item) { + head = newNode(item, head); + if (size == 0) { + tail = head; + } + size++; + } + + /** + * insertBack() inserts an item at the back of this SList. + * + * @param item is the item to be inserted. + * + * Performance: runs in O(1) time. + **/ + public void insertBack(Object item) { + if (head == null) { + head = newNode(item, null); + tail = head; + } else { + tail.next = newNode(item, null); + tail = tail.next; + } + size++; + } + + /** + * front() returns the node at the front of this SList. If the SList is + * empty, return an "invalid" node--a node with the property that any + * attempt to use it will cause an exception. + * + * @return a ListNode at the front of this SList. + * + * Performance: runs in O(1) time. + */ + public ListNode front() { + if (head == null) { + // Create an invalid node. + SListNode node = newNode(null, null); + node.myList = null; + return node; + } else { + return head; + } + } + + /** + * back() returns the node at the back of this SList. If the SList is + * empty, return an "invalid" node--a node with the property that any + * attempt to use it will cause an exception. + * + * @return a ListNode at the back of this SList. + * + * Performance: runs in O(1) time. + */ + public ListNode back() { + if (tail == null) { + // Create an invalid node. + SListNode node = newNode(null, null); + node.myList = null; + return node; + } else { + return tail; + } + } + + /** + * toString() returns a String representation of this SList. + * + * @return a String representation of this SList. + * + * Performance: runs in O(n) time, where n is the length of the list. + */ + public String toString() { + String result = "[ "; + SListNode current = head; + while (current != null) { + result = result + current.item + " "; + current = current.next; + } + return result + "]"; + } + + private static void testInvalidNode(ListNode p) { + System.out.println("p.isValidNode() should be false: " + p.isValidNode()); + try { + p.item(); + System.out.println("p.item() should throw an exception, but didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.item() should throw an exception, and did."); + } + try { + p.setItem(new Integer(0)); + System.out.println("p.setItem() should throw an exception, but didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.setItem() should throw an exception, and did."); + } + try { + p.next(); + System.out.println("p.next() should throw an exception, but didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.next() should throw an exception, and did."); + } + try { + p.prev(); + System.out.println("p.prev() should throw an exception, but didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.prev() should throw an exception, and did."); + } + try { + p.insertBefore(new Integer(1)); + System.out.println("p.insertBefore() should throw an exception, but " + + "didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.insertBefore() should throw an exception, and did." + ); + } + try { + p.insertAfter(new Integer(1)); + System.out.println("p.insertAfter() should throw an exception, but " + + "didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.insertAfter() should throw an exception, and did." + ); + } + try { + p.remove(); + System.out.println("p.remove() should throw an exception, but didn't."); + } catch (InvalidNodeException lbe) { + System.out.println("p.remove() should throw an exception, and did."); + } + } + + private static void testEmpty() { + List l = new SList(); + System.out.println("An empty list should be [ ]: " + l); + System.out.println("l.isEmpty() should be true: " + l.isEmpty()); + System.out.println("l.length() should be 0: " + l.length()); + System.out.println("Finding front node p of l."); + ListNode p = l.front(); + testInvalidNode(p); + System.out.println("Finding back node p of l."); + p = l.back(); + testInvalidNode(p); + l.insertFront(new Integer(10)); + System.out.println("l after insertFront(10) should be [ 10 ]: " + l); + } + + public static void main(String[] argv) { + testEmpty(); + List l = new SList(); + l.insertFront(new Integer(3)); + l.insertFront(new Integer(2)); + l.insertFront(new Integer(1)); + System.out.println("l is a list of 3 elements: " + l); + try { + ListNode n; + int i = 1; + for (n = l.front(); n.isValidNode(); n = n.next()) { + System.out.println("n.item() should be " + i + ": " + n.item()); + n.setItem(new Integer(((Integer) n.item()).intValue() * 2)); + System.out.println("n.item() should be " + 2 * i + ": " + n.item()); + i++; + } + System.out.println("After doubling all elements of l: " + l); + testInvalidNode(n); + + i = 6; + for (n = l.back(); n.isValidNode(); n = n.prev()) { + System.out.println("n.item() should be " + i + ": " + n.item()); + n.setItem(new Integer(((Integer) n.item()).intValue() * 2)); + System.out.println("n.item() should be " + 2 * i + ": " + n.item()); + i = i - 2; + } + System.out.println("After doubling all elements of l again: " + l); + testInvalidNode(n); + + n = l.front().next(); + System.out.println("Removing middle element (8) of l: " + n.item()); + n.remove(); + System.out.println("l is now: " + l); + testInvalidNode(n); + n = l.back(); + System.out.println("Removing end element (12) of l: " + n.item()); + n.remove(); + System.out.println("l is now: " + l); + testInvalidNode(n); + + n = l.front(); + System.out.println("Removing first element (4) of l: " + n.item()); + n.remove(); + System.out.println("l is now: " + l); + testInvalidNode(n); + } catch (InvalidNodeException lbe) { + System.err.println ("Caught InvalidNodeException that should not happen." + ); + System.err.println ("Aborting the testing code."); + } + } +} diff --git a/src/com/SimpleDrawingApp/list/SListNode.class b/src/com/SimpleDrawingApp/list/SListNode.class new file mode 100644 index 0000000..88ca15c Binary files /dev/null and b/src/com/SimpleDrawingApp/list/SListNode.class differ diff --git a/src/com/SimpleDrawingApp/list/SListNode.java b/src/com/SimpleDrawingApp/list/SListNode.java new file mode 100644 index 0000000..a86afb1 --- /dev/null +++ b/src/com/SimpleDrawingApp/list/SListNode.java @@ -0,0 +1,159 @@ +/* SListNode.java */ + +package com.SimpleDrawingApp.list; + +/** + * An SListNode is a mutable node in an SList (singly-linked list). + **/ + +public class SListNode extends ListNode { + + /** + * (inherited) item references the item stored in the current node. + * (inherited) myList references the List that contains this node. + * next references the next node in the SList. + * + * DO NOT CHANGE THE FOLLOWING FIELD DECLARATIONS. + **/ + + protected SListNode next; + + /** + * SListNode() constructor. + * @param i the item to store in the node. + * @param l the list this node is in. + * @param n the node following this node. + */ + SListNode(Object i, SList l, SListNode n) { + item = i; + myList = l; + next = n; + } + + /** + * next() returns the node following this node. If this node is invalid, + * throws an exception. + * + * @return the node following this node. + * @exception InvalidNodeException if this node is not valid. + * + * Performance: runs in O(1) time. + */ + public ListNode next() throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException("next() called on invalid node"); + } + if (next == null) { + // Create an invalid node. + SListNode node = ((SList) myList).newNode(null, null); + node.myList = null; + return node; + } else { + return next; + } + } + + /** + * prev() returns the node preceding this node. If this node is invalid, + * throws an exception. + * + * @param node the node whose predecessor is sought. + * @return the node preceding this node. + * @exception InvalidNodeException if this node is not valid. + * + * Performance: runs in O(this.size) time. + */ + public ListNode prev() throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException("prev() called on invalid node"); + } + SListNode prev = ((SList) myList).head; + if (prev == this) { + // Create an invalid node. + prev = ((SList) myList).newNode(null, null); + prev.myList = null; + } else { + while (prev.next != this) { + prev = prev.next; + } + } + return prev; + } + + /** + * insertAfter() inserts an item immediately following this node. If this + * node is invalid, throws an exception. + * + * @param item the item to be inserted. + * @exception InvalidNodeException if this node is not valid. + * + * Performance: runs in O(1) time. + */ + public void insertAfter(Object item) throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException("insertAfter() called on invalid node"); + } + SListNode newNode = ((SList) myList).newNode(item, next); + if (next == null) { + ((SList) myList).tail = newNode; + } + next = newNode; + myList.size++; + } + + /** + * insertBefore() inserts an item immediately preceding this node. If this + * node is invalid, throws an exception. + * + * @param item the item to be inserted. + * @exception InvalidNodeException if this node is not valid. + * + * Performance: runs in O(this.size) time. + */ + public void insertBefore(Object item) throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException("insertBefore() called on invalid node"); + } + SListNode newNode = ((SList) myList).newNode(item, this); + if (this == ((SList) myList).head) { + ((SList) myList).head = newNode; + } else { + SListNode prev = (SListNode) prev(); + prev.next = newNode; + } + myList.size++; + } + + /** + * remove() removes this node from its SList. If this node is invalid, + * throws an exception. + * + * @exception InvalidNodeException if this node is not valid. + * + * Performance: runs in O(this.size) time. + */ + public void remove() throws InvalidNodeException { + if (!isValidNode()) { + throw new InvalidNodeException("remove() called on invalid node"); + } + if (this == ((SList) myList).head) { + ((SList) myList).head = next; + if (next == null) { + ((SList) myList).tail = null; + } + } else { + SListNode prev = (SListNode) prev(); + prev.next = next; + if (next == null) { + ((SList) myList).tail = prev; + } + } + myList.size--; + + // Make this node an invalid node, so it cannot be used to corrupt myList. + myList = null; + // Set other reference to null to improve garbage collection. + next = null; + } + +}