From 605394549486ea63fbe8a2da3ff028ab1ae6a28b Mon Sep 17 00:00:00 2001 From: Thomas Leonard Date: Fri, 14 Jun 2002 16:00:11 +0000 Subject: [PATCH] Foreach and Enter blocks. git-svn-id: http://dom-editor.googlecode.com/svn/trunk@294 ef21e15d-ca94-4315-9c45-0d95b1b2e117 --- Dome/Display.py | 2 +- Dome/List.py | 73 ++++++++++++++++++++++++++++++++++++++------------------- Dome/Program.py | 30 +++++++++++++++++++----- Dome/View.py | 44 +++++++++++++++++++++++++++------- 4 files changed, 109 insertions(+), 40 deletions(-) diff --git a/Dome/Display.py b/Dome/Display.py index 91403f1..14aca1e 100644 --- a/Dome/Display.py +++ b/Dome/Display.py @@ -110,7 +110,7 @@ class Display(GnomeCanvas): return # Going to update anyway... if self.view.running(): - self.update_timeout = timeout_add(10000, self.update_callback) + self.update_timeout = timeout_add(2000, self.update_callback) else: self.update_timeout = timeout_add(10, self.update_callback) diff --git a/Dome/List.py b/Dome/List.py index a1557be..2519986 100644 --- a/Dome/List.py +++ b/Dome/List.py @@ -421,8 +421,20 @@ class ChainDisplay(GnomeCanvas): g = group.add('group', x = 0, y = 0) self.create_node(op.start, g) (lx, ly, hx, hy) = g.get_bounds() - g.add('rect', x1 = lx - 4, x2 = hx + 4, y1 = ly - 4, y2 = hy + 4, - outline_color = 'black', width_pixels = 1) + minx = lx - 4 + if op.foreach: + minx -= 8 + border = g.add('rect', x1 = minx, x2 = hx + 4, y1 = ly + 4, y2 = hy + 4, + outline_color = 'black', width_pixels = 1) + border.lower_to_bottom() + if op.foreach: + g.add('rect', x1 = minx, x2 = minx + 8, y1 = ly + 4, y2 = hy + 4, + fill_color = 'blue').lower_to_bottom() + if op.enter: + g.add('rect', x1 = minx, x2 = hx + 4, y1 = ly + 5, y2 = ly + 13, + fill_color = 'yellow').lower_to_bottom() + g.add('rect', x1 = minx, x2 = hx + 4, y1 = hy - 3, y2 = hy + 3, + fill_color = 'yellow').lower_to_bottom() next_off_y = 0 group.width, group.height = hx, hy if op.is_toplevel(): @@ -437,17 +449,20 @@ class ChainDisplay(GnomeCanvas): y1 = -4, y2 = 4, width_pixels = 1) group.ellipse.connect('event', self.op_event, op) - label = group.add('text', - x = -8, - y = -8, - anchor = ANCHOR_NE, - justification = 'right', - font = 'fixed', - fill_color = 'black', - text = text) - - (lx, ly, hx, hy) = label.get_bounds() - next_off_y = hy + if op.action[0] != 'Start': + label = group.add('text', + x = -8, + y = -8, + anchor = ANCHOR_NE, + justification = 'right', + font = 'fixed', + fill_color = 'black', + text = text) + + (lx, ly, hx, hy) = label.get_bounds() + next_off_y = hy + else: + next_off_y = 0 group.width, group.height = 0, 0 if op.next and op.next.prev[0] == op: @@ -583,24 +598,29 @@ class ChainDisplay(GnomeCanvas): self.update_points() def show_op_menu(self, event, op): + if op.action[0] == 'Start': + op = op.parent + items = [('Toggle Enter/Leave', lambda: op.toggle_enter()), + ('Toggle Foreach', lambda: op.toggle_foreach())] + else: + items = [('Edit node', lambda: self.edit_op(op))] + del_node = None - - def swap_nf(self = self, op = op): - op.swap_nf() - if not (op.next and op.fail): def del_node(self = self, op = op): self.clipboard = op.del_node() - items = [('Edit node', lambda: self.edit_op(op)), - ('Swap next/fail', swap_nf), - ('Remove node', del_node)] + + items += [('Swap next/fail', lambda: op.swap_nf()), ('Remove node', del_node)] Menu(items).popup(event.button, event.time) def paste_chain(self, op, exit): print "Paste", self.clipboard doc = self.clipboard new = load(doc.documentElement, op.parent) - op.link_to(new, exit) + start = new.start.next + new.start.unlink('next', may_delete = 0) + start.set_parent(None) + op.link_to(start, exit) def end_link_drag(self, item, event, src_op, exit): # Scan all the nodes looking for one nearby... @@ -724,9 +744,14 @@ class ChainDisplay(GnomeCanvas): x1, y1 = self.get_arrow_start(op, exit) if op2: - group = self.op_to_group[op2] - x2, y2 = group.i2w(0, 0) - x2, y2 = prev_group.w2i(x2, y2) + try: + group = self.op_to_group[op2] + except: + x2 = x1 + 50 + y2 = y1 + 50 + else: + x2, y2 = group.i2w(0, 0) + x2, y2 = prev_group.w2i(x2, y2) elif exit == 'next': x2, y2 = DEFAULT_NEXT x2 += x1 diff --git a/Dome/Program.py b/Dome/Program.py index 34067d3..491f79f 100644 --- a/Dome/Program.py +++ b/Dome/Program.py @@ -14,7 +14,14 @@ def load(node, parent): #assert node.localName == 'block' block = Block(parent) - prev = block.start + try: + if int(node.getAttributeNS(None, 'foreach')): + block.toggle_foreach() + if int(node.getAttributeNS(None, 'enter')): + block.toggle_enter() + prev = block.start + except: + pass id_hash = {} # id from file -> Op to_link = [] @@ -214,7 +221,7 @@ class Op: def set_parent(self, parent): if self.parent == parent: return - if self.parent: + if parent and self.parent: raise Exception('Already got a parent!') nearby = self.prev[:] if self.next: @@ -225,17 +232,16 @@ class Op: [x.set_parent(parent) for x in nearby if x.parent is not parent] def changed(self, op = None): - if self.parent: - self.parent.changed(op or self) + self.parent.changed(op or self) def swap_nf(self): + assert self.action[0] != 'Start' self.next, self.fail = (self.fail, self.next) self.changed() def link_to(self, child, exit): # Create a link from this exit to this child Op assert self.action[0] != 'Start' or exit == 'next' - print child.action assert child.action[0] != 'Start' print "Link %s:%s -> %s" % (self, exit, child) @@ -390,7 +396,9 @@ class Block(Op): self.parent = parent self.start = Op() self.start.parent = self - + self.foreach = 0 + self.enter = 0 + def set_start(self, start): assert not start.prev @@ -407,7 +415,17 @@ class Block(Op): def to_xml(self, doc): node = doc.createElementNS(DOME_NS, 'block') + node.setAttributeNS(None, 'foreach', str(self.foreach)) + node.setAttributeNS(None, 'enter', str(self.enter)) assert not self.start.fail if self.start.next: self.start.next.to_xml_int(node) return node + + def toggle_enter(self): + self.enter = not self.enter + self.changed() + + def toggle_foreach(self): + self.foreach = not self.foreach + self.changed() diff --git a/Dome/View.py b/Dome/View.py index 9984ca2..62d8ed5 100644 --- a/Dome/View.py +++ b/Dome/View.py @@ -142,6 +142,7 @@ class View: self.single_step = 1 # 0 = Play 1 = Step-into 2 = Step-over self.model = None self.chroots = [] # (model, node, marked) + self.foreach_stack = [] # (block, [nodes]) self.current_nodes = [] self.clipboard = None self.current_attrib = None @@ -520,7 +521,8 @@ class View: # If we're in a block, try exiting from it... if isinstance(op.parent, Block): - self.leave_block(op.parent) + if self.start_block_iteration(op.parent): + return # Looping... if not op.parent.is_toplevel(): self.set_exec((op.parent, exit)) return @@ -895,27 +897,50 @@ class View: if self.op_in_progress: self.push_stack(self.op_in_progress) self.set_oip(None) - self.play_block(self, prog.code) + self.play_block(prog.code) self.sched() self.status_changed() raise InProgress + def start_block_iteration(self, block): + "True if we are going to run the block, False to exit the loop" + if not self.foreach_stack: + raise Exception("Reached the end of a block we never entered!") + stack_block, nodes_list = self.foreach_stack[-1] + if stack_block != block: + self.foreach_stack = [] + raise Exception("Reached the end of a block we never entered!") + if not nodes_list: + self.foreach_stack.pop() + return 0 # Nothing left to do + nodes = nodes_list[0] + del nodes_list[0] + self.move_to(nodes) + + if block.enter: + self.enter() + self.set_exec((block.start, 'next')) + return 1 + def play_block(self, block): assert isinstance(block, Block) - self.set_exec((block.start, 'next')) + print "Enter Block!" + if block.foreach: + list = self.current_nodes[:] + else: + list = [self.current_nodes[:]] # List of one item, containing everything + + self.foreach_stack.append((block, list)) + self.start_block_iteration(block) def Block(self): - print "Enter Block!" assert self.op_in_progress oip = self.op_in_progress self.set_oip(None) self.play_block(oip) + self.sched() raise InProgress - def leave_block(self, block): - # Do any tidying up - print "Leaving block", block - def sched(self): if self.op_in_progress: raise Exception("Operation in progress") @@ -951,7 +976,8 @@ class View: print "Error in do_one_step(): stopping playback" node = self.op_in_progress self.set_oip(None) - self.set_exec((node, 'fail')) + if node: + self.set_exec((node, 'fail')) self.status_changed() return 0 if self.op_in_progress or self.single_step: -- 2.11.4.GIT