Question: /* LinkList * Anderson, Franceschi */ /** * this class is a concrete implementation of the AbstractList. * * properties of this implementation are such

/* LinkList * Anderson, Franceschi */

/** * this class is a concrete implementation of the AbstractList. * * properties of this implementation are such that: - the list is singly linked * - data contained in the nodes is limited to integers - nodes are sorted in * ascending order of data - duplicate data is allowed - note that duplicate * data may cause inconsistent behavior in the Visualizer because the delete * method searches for the first instance of data. if a node besides the first * one is highlighted, the first one will still be deleted. */ public class LinkList extends AbstractList { private Node head = null;

public LinkList() { super(500, 400); v.drawList(head); }

public LinkList(Node head) { super(500, 400); // set size for visualizer // set up the list head = head;

animate(head); }

public void insert(int i) { // ***** Student writes the body of this method *****

// code the insert method of a linked list of ints // the int to insert in the linked list is i

// we call the animate method inside the body of this method // as you traverse the list looking for the place to insert, // call animate as follows:

// animate(head, current); // where head is the instance variable head of the linked list // current is the node that you are visiting

// you can start coding now

// in order to improve the animation (this is optional): // just before inserting, i.e. connecting the nodes, // make the call

// animate(head, previous, Visualizer.ACTION_INSERT_AFTER);

// where head is the instance variable head of the linked list // previous is the node (not null) after which to insert

// if you are inserting at the beginning of the list, // just before inserting, make the call

// animate(head, head, Visualizer.ACTION_INSERT_BEFORE);

// where head is the instance variable head of the linked list // // Part 1 student code starts here:

// Part 1 student code ends here.

numberNodes++; // call animate again to show the status of the list animate(head); }

public boolean delete(int i) { // ***** Student writes the body of this method *****

// code the delete method of a linked list of ints // the int to delete in the linked list is i // if deletion is successful, return true // otherwise, return false

// we call the animate method inside the body of this method // as you traverse the list looking for the node to delete, // call animate as follows:

// animate(head, current);

// where head is the instance variable head of the linked list // current is the node that you are visiting

// you can start coding now

// in order to improve the animation (this is optional): // just before deleting, i.e. connecting the nodes, // make the call

// animate(head, current, Visualizer.ACTION_DELETE);

// where head is the instance variable head of the linked list // current is the node that you are deleting // // Part 2 student code starts here:

// Part 2 student code ends here.

// At this point, the item has been deleted. // Decrement the number of nodes: numberNodes--; // Call animate again to show the status of the list: animate(head); return true; }

public int count() { int n = 0; Node current = head; while (current != null) { animate(head, current); n++; current = current.getNext(); } return n; }

public void traverse() { traversal = ""; Node current = head; while (current != null) { animate(head, current); traversal += (current.getData() + " "); current = current.getNext(); } v.drawList(head); }

public void clear() { head = null; v.drawList(head); }

public void animate(Node h, Node nd) { v.drawList(h, nd); delay(1000); }

public void animate(Node h) { v.drawList(h); }

public void animate(Node h, Node nd, int mode) { v.drawList(h, nd, mode); delay(1000); } }

/* AbstractList * Anderson, Franceschi */

public abstract class AbstractList { /* INSTANCE VARIABLES */

/** * a Visualizer instance is maintained here so that the student * can call it from the child class without worrying about the * implementation of the Visualizer. This is intended to mimic * the use of a Graphic object in the Swing or AWT package. **/ protected Visualizer v;

protected int numberNodes; protected String traversal; // holds current traversal of the list

/* CONSTRUCTORS */

/** * instantiate with the given GUI width and height for the Visualizer. * **/ public AbstractList( int width, int height ) { v = new Visualizer( width, height ); numberNodes = 0; }

/* METHODS STUDENTS MUST OVERRIDE */

/** * * insert an object in to the list. * **/ public abstract void insert( int i );

/** * * delete a node from the list based on reference. * * @ return true if the node was deleted, false otherwise **/

/** * * delete a node from the list based on data. * * @return true if the node was deleted, false otherwise * **/ public abstract boolean delete( int i );

/** * * returns the number of Nodes in the list. * **/ public abstract int count( );

/** * * walks the list and displays the data it contains. * **/ public abstract void traverse( );

/** * * removes all nodes from the list. * **/ public abstract void clear( );

/* METHODS FOR CONTROLLING VISUALIZER */

/** * * sets the width and height in pixels for the visualizer. * **/ public void setSize( int width, int height ) { v.setSize( width, height ); v.validate( ); }

/** * * returns a reference to the Visualizer being used by this object. * Any object calling this method is on its honor to not modify * the Visualizer. * **/ public Visualizer getVisualizer( ) { return v; }

/** * * simple delay routine that makes the thread sleep for the given * number of milliseconds. useful for when a node is being * highlighted by the visualizer. * **/ public void delay( int milliseconds ) { try { Thread.sleep( milliseconds ); } catch ( Exception e ) { System.out.println(" e: "+e ); } }

/* * * the following are wrapper methods to make calling the visualizer * a little more convienient. see the wrapped Visualizer methods * for more information. * */ /* public void drawList( Node headNode ) { v.drawList( headNode ); }

public void drawList( Node headNode, int highlight ) { v.drawList( headNode, highlight ); }

public void drawList( Node headNode, Node highlight ) { v.drawList( headNode, highlight ); }

public void drawList( Node headNode, int target, int action ) { v.drawList( headNode, target, action ); }

public void drawList( Node headNode, Node target, int action ) { v.drawList( headNode, target, action ); } */ public String getTraversal( ) { return traversal; }

} // end abstract list

/* LinkedListPractice * Anderson, Franceschi */

import java.awt.*; import java.awt.event.*; import javax.swing.*;

public class LinkedListPractice extends JFrame { /* INSTANCE VARIABLES These variables are directly responsible for handling the student code: instantiating an object of the student's list, displaying it graphically, manipulating it by calling the various methods. */

/** * rationale: use AbstractList so that an instructor can have * students create any other list type and still * be able to use all the same method calls. The only * change that needs to be made to this code is * changing the instantiation to whatever type the * instructor wants. **/ private AbstractList list;

/** * this class is on its honor to not modify the Visualizer. * the list instance returns a reference to its Visualizer * so that this class can add it in to the JFrame, but this * class should never directly modify that instance. **/ private Visualizer v;

/* GUI ELEMENTS */

// controls private JPanel controls; // holds the following: private JPanel dataPanel; // text box and label private JButton insertNode; private JButton deleteNode; private JButton traverseList; private JButton clearList; private JButton countNodes;

private JTextField data; // text box and label private JLabel dataLabel; // for dataPanel

// output private JScrollPane outputPane; // holds the output text area private JTextArea outputArea; // the output text area private String outputDisplay = ""; // message to outputArea private JScrollPane visualPane; // holds the Visualizer

private boolean mouseDisabled = false; // prevent clicking while drawing

private static int MAX_DATA_LENGTH = 4; // max chars allowed in the data field

/* CONSTRUCTOR */

/** * instantiates a new ListControl with the given width and height. * sets up the controls, initializes the Visualizer, makes everything * visible. * **/ public LinkedListPractice( int width, int height ) { super( ); // call to Object( ) for completeness setTitle( " Linked List Visualizer" );

// set up the list and visualizer list = new LinkList( ); v = list.getVisualizer( ); visualPane = new JScrollPane( v );

// instantiate GUI list controls

dataPanel = new JPanel( ); dataPanel.setLayout( new GridLayout( 2,1 ) );

data = new JTextField( ); dataLabel = new JLabel( "Node Data:" );

dataPanel.add( dataLabel ); dataPanel.add( data );

controls = new JPanel( ); controls.setLayout( new GridLayout( 6, 1 ) );

insertNode = new JButton( "insert" ); deleteNode = new JButton( "delete" ); traverseList = new JButton( "traverse" ); countNodes = new JButton( "count" ); clearList = new JButton( "clear" );

// set up handlers for controls // private inner classes seem more readable // than anonymous inner classes or one large handler data.addKeyListener( new DataListener( ) ); insertNode.addActionListener( new ActionInsert( ) ); deleteNode.addActionListener( new ActionDelete( ) ); traverseList.addActionListener( new ActionTraverse( ) ); countNodes.addActionListener( new ActionCount( ) ); clearList.addActionListener( new ActionClear( ) );

// add controls to the control pane controls.add( dataPanel ); controls.add( insertNode ); controls.add( deleteNode ); controls.add( traverseList ); controls.add( countNodes ); controls.add( clearList );

// set up GUI output outputArea = new JTextArea( 5, 40 ); outputPane = new JScrollPane( outputArea ); outputArea.setEditable( false );

// set up ListControl GUI setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE ); getContentPane( ).setLayout( new BorderLayout( ) ); getContentPane( ).add( visualPane,BorderLayout.CENTER ); getContentPane( ).add( controls,BorderLayout.WEST ); getContentPane( ).add( outputPane,BorderLayout.SOUTH );

setSize( width,height ); setVisible( true ); doLayout( ); validate( ); } // end default constructor

/* METHODS */

/** turn off all the buttons so they can't be clicked during operations **/ private void disableButtons( ) { insertNode.setEnabled( false ); deleteNode.setEnabled( false ); traverseList.setEnabled( false ); clearList.setEnabled( false ); countNodes.setEnabled( false ); mouseDisabled = true; }

/** turn on the buttons **/ private void enableButtons( ) { insertNode.setEnabled( true ); deleteNode.setEnabled( true ); traverseList.setEnabled( true ); clearList.setEnabled( true ); countNodes.setEnabled( true ); mouseDisabled = false; }

/** give focus to the text field and select any text it holds **/ private void selectData( ) { data.select( 0, data.getText( ).length( ) ); data.requestFocusInWindow( ); }

private int getData( ) throws NumberFormatException { return ( new Integer( data.getText( ) ) ).intValue( ); }

/* PRIVATE INNER CLASSES - action handlers each class is for a specific button, so the event source is not checked

for any method that requires nodes to be highlighted, a new thread is created and started to handle calling the method. this allows the GUI to handle the highlighting and delay routines appropriately. */

private class ActionInsert implements ActionListener { public void actionPerformed( ActionEvent e ) { //SwingUtilities.invokeLater( new InsertThread( ) ); ( new InsertThread( ) ).start( ); }

private class InsertThread extends Thread { public void run( ) { disableButtons( ); try { int i = getData( ); outputDisplay += "insert called with " + i + " as data "; outputArea.setText( outputDisplay ); list.insert(i); } catch ( Exception e ) { outputDisplay += "invalid number "; outputArea.setText( outputDisplay ); } enableButtons( ); selectData( ); } } } // end ActionInsert

private class ActionDelete implements ActionListener { public void actionPerformed( ActionEvent e ) { ( new DeleteThread( ) ).start( ); }

private class DeleteThread extends Thread { public void run( ) { disableButtons( ); outputDisplay += ( "delete called with " + data.getText( ) + ": " ); outputArea.setText( outputDisplay ); try { boolean deleted = list.delete( new Integer( data.getText( ) ).intValue( ) ); outputDisplay += "node " + ( (deleted)?"deleted ":"not found " ); outputArea.setText( outputDisplay ); } catch( NumberFormatException nfe ) { outputDisplay += ( "data not an integer " ); outputArea.setText( outputDisplay ); } enableButtons( ); selectData( ); } } }

private class ActionTraverse implements ActionListener { public void actionPerformed( ActionEvent e ) { outputDisplay += "traversing the list: "; outputArea.setText( outputDisplay ); ( new Thread( ){ public void run( ){ disableButtons( ); list.traverse( ); outputDisplay += ( list.getTraversal( ) + " " ); outputArea.setText( outputDisplay ); enableButtons( ); selectData( ); } }).start( ); } } // end ActionTraverse

private class ActionCount implements ActionListener { public void actionPerformed( ActionEvent e ) { ( new CountThread( ) ).start( ); }

private class CountThread extends Thread { public void run( ) { disableButtons( ); outputDisplay += "count called: "; outputArea.setText( outputDisplay ); int n = list.count( ); outputDisplay += ( "number of nodes = " + n + " " ); outputArea.setText( outputDisplay ); enableButtons( ); selectData( ); } } } // end ActionCount

private class ActionClear implements ActionListener { public void actionPerformed( ActionEvent e ) { ( new ClearThread( ) ).start( ); }

private class ClearThread extends Thread { public void run( ) { disableButtons( ); outputDisplay += "clear list called "; outputArea.setText( outputDisplay ); list.clear( ); enableButtons( ); selectData( ); } } } // end ActionClear

/** detects when key is entered in to data text field, and ensures that the field is limited to MAX_DATA_LENGTH. **/ private class DataListener extends KeyAdapter { int key = 0; // which key was pressed //keyPressed will detect back space, but doesn't properly consume // the event, so the field still gets it. so, trap the key here // and assign it to variable key. thankfully by its very nature // keyPressed happens before keyTyped. public void keyPressed( KeyEvent e ) { key = e.getKeyCode( ); }

// keyTyped will properly consume the event, but can't detect when // backspace was pressed. it also lets arrow keys, home, etc. through. // key has been trapped by keyPressed, so it can be properly compared // to backspace, and consumed if it is not back space and field is // over 15 chars. public void keyTyped( KeyEvent e ) { // must compare to MAX_DATA_LENGTH-1 because the key currently being examined // will be the last character in the field.

if( key == KeyEvent.VK_BACK_SPACE ) { // never consume backspace return; } if( data.getText( ).length( ) > MAX_DATA_LENGTH-1 || key < KeyEvent.VK_0 || key > KeyEvent.VK_9 ) { // if field is full, or invalid value entered, consume the key e.consume( ); return; } } }

public static void main( String args[] ) { LinkedListPractice app = new LinkedListPractice( 600, 400 ); } }

/* Node * Anderson, Franceschi */

public class Node { /** reference to the next node in the list **/ private Node nextNode;

/** the data object held by this node **/ private int data;

/** * * construct a new node with the given Object as data * **/ public Node( int i ) { data = i; }

/** * * construct a new node with the given Object as data * and references to the next and previous nodes. * **/ public Node( int i, Node next ) { data = i; nextNode = next; }

/** * * set the reference to the next node * **/ public void setNext( Node n ) { nextNode = n; }

/** * * return the reference to the next node * @return reference to the next node, or null if there is no next node * **/ public Node getNext( ) { return nextNode; }

/** * * set the data object held by this node * **/ public void setData( int i ) { data = i; }

/** * * get the data object held by this node * **/ public int getData( ) { return data; }

} // end node class

/* Visualizer * Anderson, Franceschi */

import javax.swing.*; import java.awt.*; //import java.awt.event.*; import java.util.ArrayList;

public class Visualizer extends JPanel { public static final int nodeWidth = 100; public static final int nodeHeight = 100; public static final int halfWidth = nodeWidth / 2; public static final int halfHeight = nodeHeight / 2; public static final int qrtrWidth = nodeWidth / 4; public static final int qrtrHeight = nodeHeight / 4;

public static final int nodeSpacer = halfWidth;

/** node is drawn normally **/ public static final int ACTION_NONE = 0; /** node is drawn highlighted **/ public static final int ACTION_HIGHLIGHT = 1; /** indicator is drawn after node **/ public static final int ACTION_INSERT_AFTER = 2; /** indicator is drawn before node **/ public static final int ACTION_INSERT_BEFORE = 3; /** node is drawn with delete indicator **/ public static final int ACTION_DELETE = 4; /** node is drawn with retrieve indicator **/ public static final int ACTION_RETRIEVE = 5;

private int initialHeight = 0; private ArrayList nodeData = new ArrayList( );

/** * * creates a new Visualizer with the given width * and height in pixels. sets the preferred size * to those values, and makes the Visualizer visible. * **/ public Visualizer( int width, int height ) { super( );

initialHeight = height;

setSize( width,height ); setPreferredSize( new Dimension( width, height ) ); setVisible( true ); validate( );

} // end default constructor

/** * * draws all nodes currently contained in the list of nodes. * **/ protected void paintComponent( Graphics g ) { super.paintComponent( g );

for( int n = 0; n < nodeData.size( ); n++) { nodeData.get( n ).draw( g ); }

// the following lines let the scrollpane know to update revalidate( ); } // end paintComponent

/** * * convenience method that is the same as calling * drawList(Node, null, Visualizer.ACTION_NONE) * so that the list is drawn with no nodes highlighted. * **/ public synchronized void drawList( Node head ) { nodeData.clear( ); Node current = head; //highlightData = target; //this.action = action; int x = nodeSpacer; int y = 50;

while( current != null ) { nodeData.add( new NodeWrapper( current, x, y, ACTION_NONE ) );

current = current.getNext( ); x += ( nodeWidth+nodeSpacer ); } setPreferredSize( new Dimension (x + nodeWidth + nodeSpacer, initialHeight ) ); repaint( ); } // end drawList

/** * * convenience method that is the same as calling * drawList(Node,Object,Visualizer.ACTION_HIGHLIGHT) * so that the list is drawn with a node that has a data * object matching the given object highlighted. * **/ public synchronized void drawList( Node head, int highlight ) { drawList( head, highlight, Visualizer.ACTION_HIGHLIGHT ); } // end drawList with a node highlighted

public synchronized void drawList( Node head, Node highlight ) { drawList( head, highlight, Visualizer.ACTION_HIGHLIGHT ); } // end drawList with a node highlighted

/** * * draws graphical representations of link list nodes. starting * from the head node, the list is traversed in order and each * node is displayed. if a node contains a data object that is * equal to target, that node will be drawn in such a way * as to stand out from the other nodes according to the * specified action. * * @param head the head Node of a linked list. * * @param highlight a data object to be matched against the data * objects in the list. if a match is found, that * node will be highlighted. to not highlight any * nodes, send null as the highlight parameter. * * @param action the action to display upon finding a matching node. * See the ACTION_actiontype final static ints * specified by this class. * **/ public synchronized void drawList( Node head, int target, int action ) { nodeData.clear( ); Node current = head; //highlightData = target; //this.action = action; int x = nodeSpacer; int y = 50;

while( current != null ) { if( target == current.getData( ) ) { nodeData.add( new NodeWrapper( current, x, y, action ) ); action = ACTION_NONE; } else { nodeData.add( new NodeWrapper( current,x , y, ACTION_NONE ) ); } current = current.getNext( ); x += ( nodeWidth + nodeSpacer ); } setPreferredSize( new Dimension( x + nodeWidth + nodeSpacer, initialHeight ) );

repaint( ); } // end draw list (head, target, action)

/** * Draws the list as described in drawList(Node, int, int), except that * here, the target node is found by reference instead of by value. * * @param head * @param target * @param action */ public synchronized void drawList( Node head, Node target, int action ) { nodeData.clear( ); Node current = head; //highlightData = target; //this.action = action; int x = nodeSpacer; int y = 50;

while( current != null ) { if( target == current ) { nodeData.add( new NodeWrapper( current, x, y, action) ); action = ACTION_NONE; } else { nodeData.add( new NodeWrapper( current, x, y, ACTION_NONE ) ); } current = current.getNext( ); x += ( nodeWidth + nodeSpacer ); } setPreferredSize( new Dimension( x + nodeWidth + nodeSpacer, initialHeight ) );

repaint( ); } // end draw list (head, target, action)

/** draw the reference to null **/ private void drawNullRef( Graphics g, int x, int y ) { int startY = y + ( ( int ) ( nodeHeight * ( 3.0f / 4.0f) ) ); int endY = y + ( int ) ( ( nodeHeight *1.5f ) ); g.drawLine( x, startY, x, endY ); g.drawLine( x - 10, endY, x + 10, endY ); g.drawLine( x - 5, endY + 5, x + 5, endY + 5 ); } // end draw null ref

/** draw reference arrows from node to node **/ private void drawRefs( Graphics g, NodeWrapper wn ) { int x = wn.getX( ); int y = wn.getY( ); Node n = wn.getNode( ).getNext( );

if( n == null ) { drawNullRef( g, x + halfWidth, y ); } else { for( int i = 0; i < nodeData.size( ); i++ ) { NodeWrapper nw = nodeData.get( i ); if( n == nw.getNode( ) ) { int targetX = nw.getX( ); int targetY = nw.getY( ); g.fillOval( x + halfWidth, y + ( (int ) ( nodeHeight * ( 3.0f / 4.0f ) ) ) - 3, 6, 6 ); g.drawLine( x + halfWidth, y + ( ( int ) ( nodeHeight * ( 3.0f / 4.0f ) ) ), x + nodeWidth + 13, y + ( ( int ) ( nodeHeight * ( 3.0f / 4.0f ) ) ) ); g.drawLine( x + nodeWidth + 13, y + ( ( int ) ( nodeHeight * ( 3.0f / 4.0f ) ) ), targetX - 13, targetY + 15 ); g.drawLine( targetX - 13, targetY + 15, targetX, targetY + 15 );

g.drawLine( targetX, targetY + 15, targetX - 7, targetY + 10 ); g.drawLine( targetX, targetY + 15, targetX - 7, targetY + 20 );

break; } } } } // end draw refs

/** * * detect if there is a node at the given the x,y coordinate. if * there is, it will be highlighted and that node will be returned. * * @return the node at the given coordinate, or null if there is no * node at the coordinate * **/ public Node selectNode( int mouseX, int mouseY ) { int x = 0; int y = 0;

int size = nodeData.size( ); Node n = null; for( int i = 0; i < size; i++ ) { x = nodeData.get( i ).getX( ); y = nodeData.get( i ).getY( );

if( x < mouseX && mouseX < x + nodeWidth && y < mouseY && mouseY < y + nodeHeight ) { // if it was selected, hightlight it ( nodeData.get( i ) ).setAction( ACTION_HIGHLIGHT );

// output.put( "panel clicked: \"" + ( nodeData.get( i ) ).getNode( ).getData( )+"\" selected" ); n = ( nodeData.get( i ) ).getNode( );

} else { // otherwise, no special treatment ( nodeData.get( i ) ).setAction( ACTION_NONE ); } } repaint( ); return n; } // end selectNode at coordinate

/** wraps a Node with extra information so it can be displayed in the Visualizer. **/ private class NodeWrapper { int nodeAction = ACTION_NONE; Node node = null; int x = 0; int y = 0;

NodeWrapper( Node n, int x, int y, int action ) { this.nodeAction = action; this.node = n; this.x = x; this.y = y;

}

public Node getNode( ) { return node; }

public int getX( ) { return x; }

public int getY( ) { return y; }

public void setAction( int action ) { this.nodeAction = action; }

/** draw the node at current x,y coord with current action type **/ void draw( Graphics g ) { // draw the node representation g.setColor( Color.BLACK ); g.drawRect( x, y, nodeWidth, nodeHeight ); // main rectangle g.drawLine( x, y + halfHeight, x + nodeWidth, y + halfHeight ); //horizontal line //g.drawLine( x + halfWidth, y + halfHeight, x + halfWidth,y+nodeHeight ); // vertical line

// in case the data.toString is really long, this will shrink the // font size so that it fits in the node drawing. int fontSize = 16; Font font = new Font( "SansSerif", Font.PLAIN, fontSize ); FontMetrics metrics = getFontMetrics( font ); String str = ""+node.getData( ); while( fontSize > 0 && metrics.stringWidth( str ) > nodeWidth - 10 ) { //System.out.println( "str: " + str + " width: " + metrics.stringWidth( str ) + " size: " + fontSize ); font = new Font( "SansSerif", Font.PLAIN, fontSize-- ); metrics = getFontMetrics( font ); }

g.setFont( font );

g.drawString( str, x + 5, y + 20 ); // data as a string

// draw the reference arrows drawRefs( g, this );

// determine which action should be used, draw anything special for it. if( nodeAction == ACTION_HIGHLIGHT ) { g.setColor( Color.BLUE ); g.drawRect( x, y, nodeWidth, nodeHeight ); // main rectangle g.drawLine( x, y + halfHeight, x + nodeWidth, y + halfHeight ); //horizontal line // g.drawLine(x+halfWidth,y+halfHeight,x+halfWidth,y+nodeHeight); // vertical line g.drawString(str,x+5,y+20); g.setColor(Color.magenta); drawRefs(g,this); } else if( nodeAction == ACTION_INSERT_BEFORE ) { g.setColor( Color.GREEN ); int offset = nodeSpacer>>1; g.drawLine( x - offset, y, x - offset, y - 30 ); // arrow shaft g.drawLine( x - offset, y, x - offset + 5, y - 10 ); // arrow left g.drawLine( x - offset, y, x - offset - 5, y - 10 ); // arrow right } else if( nodeAction == ACTION_INSERT_AFTER ) { g.setColor( Color.GREEN ); int offset = nodeSpacer >> 1; g.drawLine( x + nodeWidth + offset, y, x + nodeWidth + offset, y - 30 ); // arrow shaft g.drawLine( x + nodeWidth + offset, y, x + nodeWidth + offset + 5, y - 10 ); // arrow left g.drawLine( x + nodeWidth + offset, y, x + nodeWidth + offset - 5, y - 10 ); // arrow right } else if( nodeAction == ACTION_DELETE ) { g.setColor( Color.red ); g.drawLine( x - 10, y - 10, x + nodeWidth + 10, y + nodeHeight + 10 ); g.drawLine( x - 10, y + nodeHeight + 10, x + nodeWidth + 10, y - 10 ); } else if( nodeAction == ACTION_RETRIEVE ) { g.setColor( Color.YELLOW ); g.drawRect( x - 10, y - 10, nodeWidth + 20, nodeHeight + 20 ); } // end drawing decision block

} // end draw

} // end node wrapper

} // end visualizer

Please only answer if you know the output so I do not lose any of my remaining question. Thank you.

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Databases Questions!