committing everything FIRST POST
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.SimpleDrawingApp"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-sdk android:minSdkVersion="7" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher"
|
||||
android:label="@string/app_name" >
|
||||
<activity
|
||||
android:name=".SimpleDrawingAppActivity"
|
||||
android:label="@string/app_name" >
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1 @@
|
|||
This is a very simple drawing app that just displays a square everywhere you drag your finger. That's it.
|
|
@ -0,0 +1,3 @@
|
|||
# cache for current jar dependecy. DO NOT EDIT.
|
||||
# format is <lastModified> <length> <SHA-1> <path>
|
||||
# Encoding is UTF-8
|
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,6 @@
|
|||
/** Automatically generated file. DO NOT MODIFY */
|
||||
package com.SimpleDrawingApp;
|
||||
|
||||
public final class BuildConfig {
|
||||
public final static boolean DEBUG = true;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 *;
|
||||
#}
|
|
@ -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
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/hello" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="hello">Hello World, SimpleDrawingAppActivity!</string>
|
||||
<string name="app_name">SimpleDrawingApp</string>
|
||||
|
||||
</resources>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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() {
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|