note legal: "See notice at end of class." status: "See notice at end of class." class TWO_WAY_TREE_DEMO inherit TOP_DEMO redefine cycle, execute, fill_menu, make end create make feature {NONE} -- Creation make -- Initialize and execute demonstration. do Precursor driver.new_menu ("%N%N* GENERAL TREE DEMO *%N%N[XX] Shows current node, (YY) shows child cursor%N") fill_menu create tree_root.make (0) active := tree_root cycle end feature {NONE} -- Attributes child, parent, right, left, root, child_forth, child_back, child_start, child_finish, child_put, put_left, put_right, child_remove, put, show, quit: INTEGER -- Command code. tree_root: TWO_WAY_TREE [INTEGER] -- Structure to operate on. active: TWO_WAY_TREE [INTEGER] -- Currently selected node in the tree. active_child: detachable TWO_WAY_TREE [INTEGER] -- Currently selected child. feature {NONE} -- Basic operations cycle -- Basic user interaction process. local new_command: INTEGER do from driver.print_menu tree_trace (tree_root, 0) new_command := driver.get_choice until new_command = quit loop execute (new_command) active_child := active.child driver.new_line driver.start_result tree_trace (tree_root, 0) driver.end_result new_command := driver.get_choice end driver.exit end tree_trace (t: TWO_WAY_TREE [INTEGER]; i: INTEGER) -- Display `t`, indented by `i` positions. require tree_not_void: t /= Void local j: INTEGER c: CURSOR do from j := 1 until j > i loop driver.putstring (" ") j := j + 1 end if t = active then driver.putstring ("[") driver.putint (t.item) driver.putstring ("]") elseif t = active_child then driver.putstring ("(") driver.putint (t.item) driver.putstring (")") else driver.putstring (" ") driver.putint (t.item) driver.putstring (" ") end driver.new_line from c := t.child_cursor t.child_start until t.exhausted loop if attached t.child as x then tree_trace (x, i + 3) end t.child_forth end t.child_go_to (c) end fill_menu -- Fill the menu with available commands. do driver.add_entry ("IL (Insert at Left): Insert new child at left of cursor position", "Change value of child to the left of child cursor position") put_left := driver.last_entry driver.add_entry ("IR (Insert at Right): Insert new child at right of cursor position", "Change value of child to the right of child cursor position") put_right := driver.last_entry driver.add_entry ("PU (PUt): Change value of current node", "Change value of current node") put := driver.last_entry driver.add_entry ("CC (Change Child): Change value of child at cursor position", "Change value of child at child cursor position") child_put := driver.last_entry driver.add_entry ("RM (ReMove): Remove child at cursor position", "Remove active child at child cursor position") child_remove := driver.last_entry driver.add_entry ("LE (LEft): Go to left sibling", "Go to left sibling of current node") left := driver.last_entry driver.add_entry ("RI (RIght): Go to right sibling", "Go to right sibling of current node") right := driver.last_entry driver.add_entry ("CH (CHild): Go to child at cursor position", "Go to active child of current node") child := driver.last_entry driver.add_entry ("PA (PArent): Go to parent", "Go to parent of current node") parent := driver.last_entry driver.add_entry ("RO (ROot): Go to root", "Go to root of tree") root := driver.last_entry driver.add_entry ("CS (Cursor Start): Move cursor to first child", "Move child cursor to first child") child_start := driver.last_entry driver.add_entry ("CE (Cursor End): Move cursor to last child", "Move child cursor to last child") child_finish := driver.last_entry driver.add_entry ("CF (Cursor Forward): Move cursor to next child", "Move child cursor forward") child_forth := driver.last_entry driver.add_entry ("CB (Cursor Backward): Move cursor to previous child", "Move child cursor backward") child_back := driver.last_entry driver.add_entry ("SH (SHow): SHow tree in full", "Display the structure and contents of the tree") show := driver.last_entry driver.add_entry ("QU (QUit)", "Terminate this session") quit := driver.last_entry driver.complete_menu end execute (new_command: INTEGER) -- Execute command corresponding to user's request. do --| parse and perform action if new_command = child then if active.is_leaf or else not attached active.child as c then driver.signal_error ("Cannot execute: no child.") else active := c end elseif new_command = parent then if active = tree_root then driver.signal_error ("Cannot execute: no parent.") else -- There is a parent because this is not a top node. check attached active.parent as p then active := p end end elseif new_command = right then if attached active.right_sibling as other then active := other if attached active.parent as p then p.child_forth end else driver.signal_error ("Cannot execute: no right sibling.") end elseif new_command = left then if attached active.left_sibling as other then active := other if attached active.parent as p then p.child_back end else driver.signal_error ("Cannot execute: no left sibling.") end elseif new_command = root then active := tree_root elseif new_command = child_forth then if active.is_leaf or else active.child_islast then driver.signal_error ("Cannot execute: no child forward.") else active.child_forth end elseif new_command = child_back then if active.is_leaf or else active.child_isfirst then driver.signal_error ("Cannot execute: no child backward.") else active.child_back end elseif new_command = child_start then if active.is_leaf then driver.signal_error ("Cannot execute: no child.") else active.child_start end elseif new_command = child_finish then if active.is_leaf then driver.signal_error ("Cannot execute: no child.") else active.child_finish end elseif new_command = put_left then if active.child_before then active.child_forth end active.child_put_left (driver.get_integer ("item")) if active.arity = 1 then active.child_start end elseif new_command = put_right then active.child_put_right (driver.get_integer ("item")) if active.arity = 1 then active.child_start end elseif new_command = child_put then if active.child_off then driver.signal_error ("Cannot execute: no active child.") else active.child_put (driver.get_integer ("item")) end elseif new_command = put then active.put (driver.get_integer ("item")) elseif new_command = child_remove then if active.is_leaf then driver.signal_error ("Cannot execute: no child.") else active.remove_child if active.child_after and not active.is_empty then active.child_back end end elseif new_command /= show then driver.signal_error ("Unknown command") end end note date: "$Date$" revision: "$Revision$" copyright: "Copyright (c) 1984-2017, Eiffel Software and others" license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)" source: "[ Eiffel Software 5949 Hollister Ave., Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end