
| Current Path : /home/cgabriel/20_dev/12_procpy/dataninja/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //home/cgabriel/20_dev/12_procpy/dataninja/swimlane.py |
import os,sys,re,tkinter,procpy
try:
import tkinter.ttk,Pmw # ,tkintertable
except:
import pip
pip.main(["install","pyttk"])
pip.main(["install","Pmw"])
# pip.main(["install","tkintertable"])
import tkinter.ttk,Pmw # ,tkintertable
import tkinter.scrolledtext
import procpy.config
import procpy.block
#************************************************************************
class Swimlane (procpy.block.Block):
def generate_shape (self,shape):
(x0,y0,x1,y1,x,y,w,h) = self.box_coord()
self.elems = { "SHAPE": self.canvas.create_rectangle(0,0,0,0,fill=self.color) }
self.contentframe = tkinter.Frame(self.canvas,background=self.color,bg=self.color,bd=0)
self.content = tkinter.Text(self.contentframe,wrap="char",font=("Courier",int(self.fontsize)),
borderwidth=0,insertborderwidth=0,bg=self.color,highlightcolor=self.color)
self.window = self.canvas.create_window(x,y,window=self.contentframe)
self.contentframe.grid_propagate(False)
self.content.config(state=tkinter.DISABLED)
self.elems['X1'] = self.canvas.create_line(0,0,0,0,fill='black',width=2)
self.elems['X2'] = self.canvas.create_line(0,0,0,0,fill='black',width=2)
self.canvas.tag_lower(self.elems['X1'], self.elems['X2'])
self.content.config(font=("Courier",int(self.fontsize)))
if 'content' in vars(self) and 'content_backup' in vars(self):
self.content.config(state=tkinter.NORMAL)
self.content.insert("1.0",self.content_backup) # text can be inserted only in NORMAL mode
self.content.config(state=tkinter.DISABLED)
self.elem_bindings()
self.shape = 'a'
#************************************************************************
def format_shape (self):
(x0,y0,x1,y1,x,y,w,h) = self.box_coord()
if self.shape in "rs":
if 'oldbbox' in vars(self):
self.bbox = self.oldbbox
del self.oldbbox
try:
self.elems['SHAPE'].setRect(x0,y0,w,h)
except:
self.elems['TEXT'].setGeometry(x0,y0,w,h)
self.canvas.coords(self.elems['SHAPE'],x0,y0,x1,y1)
self.contentframe.config(width=int(0.9*w),height=int(0.9*h))
self.content.place(x=0,y=0,width=int(0.9*w),height=int(0.9*h))
(x9,y9) = self.canvas.coords(self.window)
self.canvas.move(self.window,x-x9,y-y9)
self.canvas.coords(self.elems['X1'], x-0.5*w,y-0.5*h,99999999,y-0.5*h)
self.canvas.coords(self.elems['X2'], x-0.5*w,y+0.5*h,99999999,y+0.5*h)
self.content.config(font=("Courier",int(self.fontsize)))
#************************************************************************
def syntax_error (self):
text = self.content.get("1.0",tkinter.END)
if re.search(r"^[A-Za-z0-9\–\_]+\s*$", self.content.get("1.0",tkinter.END) ,re.DOTALL):
return(0)
return(1)
#************************************************************************
def press_button (self,px,py,x_root,y_root):
self.canvas.configure(cursor='sizing') # Alternative mouse pointers: arrow circle
# clock cross dotbox exchange fleur heart
self.resize_box = "" # man mouse pirate plus shuttle sizing spider
# spraycan star target tcross trek watch
self.x_root = x_root
self.y_root = y_root
(x0,y0,x1,y1,x,y,w,h) = self.box_coord()
if abs(y1 - py) < 4: # if pressing point is near the border of the box
self.resize_box = self.resize_box + "S" # mark the direction for resizing
if abs(y0 - py) < 4:
self.resize_box = self.resize_box + "N"
self.canvas.assign_elements_to_swimlanes()
self.last_event = 1
self.mouse_moves = 0
self.last_pressed = timeclock
#**********************************************************
def move (self,dx,dy,move_as_a_depending_swimlane=None):
# 1. ---- Check whether x-position of swimlane has to be moved
bed = False
depending_swimlane = None
for swimlane in self.canvas.swimlanes:
if swimlane == self: # Check whether there is an intersection with any other swimlane
continue
if (swimlane.bbox[1] < self.bbox[1] < swimlane.bbox[3] or swimlane.bbox[1] < self.bbox[3] < swimlane.bbox[3]
or self.bbox[1] < swimlane.bbox[1] < self.bbox[3] or self.bbox[1] < swimlane.bbox[3] < self.bbox[3]):
if move_as_a_depending_swimlane or self == self.canvas.hl_block[0]:
if (swimlane.bbox[1] - self.bbox[1]) * dy > 0:
depending_swimlane = swimlane
bed = True
break
else:
bed = True # block intersection
break
if bed:
if depending_swimlane:
depending_swimlane.move(dx,dy,1)
elif self.bbox[0] == 0:
self.bbox[0] = self.bbox[0] + self.canvas.zoom_factor * procpy.config.SWIMLANE_WIDTH
self.bbox[2] = self.bbox[2] + self.canvas.zoom_factor * procpy.config.SWIMLANE_WIDTH
else:
if not self.bbox[0] == 0:
self.bbox[0] = self.bbox[0] - self.canvas.zoom_factor * procpy.config.SWIMLANE_WIDTH
self.bbox[2] = self.bbox[2] - self.canvas.zoom_factor * procpy.config.SWIMLANE_WIDTH
self.bbox[1] = self.bbox[1] + dy
self.bbox[3] = self.bbox[3] + dy
self.format_shape()
for block in self.move_blocks:
block.move(0,dy)
for point in self.move_arrowpoints:
arrow = point[0]
arrowline = arrow.arrowlines[point[1]]
coords = self.canvas.coords(arrowline)
coords[point[2]] = coords[point[2]] + 0
coords[point[2]+1] = coords[point[2]+1] + dy
self.canvas.coords(arrowline,tuple(coords))
arrow.fit_description()
#************************************************************************
#************************************************************************
#************************************************************************
#************************************************************************
#************************************************************************
#************************************************************************
class Block1 (object):
def __init__ (self,mode,frame,obj):
self.mode = mode # no functionality
self.frame = frame # the gui_file-object
self.graphcanvas = frame.graphcanvas # the canvas
self.vars = [] # the variables of the block
self.text_invisible = [] # the hiddenvariables
self.arrows_in = [] # arrows coming in
self.arrows_out = [] # arrows going out
self.nr = 0 # the level of the block respecting the ancestor series
self.elems = {} # actual elems of the block (rectangle, triangle, rhombe, circle ...)
self.shape = "x" # the shape of the block
self.syntax_error = 0 # indicates whether text insinde block is valid python syntax
self.fontsize = self.canvas.zoom_factor * procpy.config.TEXT_SIZE # size of inside text
self.fkt = obj._FKT_
(x,y,w,h) = obj.BLOCK[1:5]
self.bbox = [x-w/2,y-h/2,x+w/2,y+h/2]
self.color = procpy.config.COLOR_BLOCK
self.sync_variables_to_text(obj.__dict__,obj.BLOCK[5:])
self.text = re.sub(r"$","",self.text,99999999)
if len(obj.BLOCK) > 5 and not obj.BLOCK[5] == "":
self.color = obj.BLOCK[5]
m = re.search(r"^([A-Za-z]+)([0]+)$",self.fkt) # choose a new name
if m:
zaehler = 0
formheader = "%0"+str(len(m.group(2)))+"u"
while (0 == 0):
zaehler = zaehler + 1
self.fkt = m.group(1) + (formheader % zaehler)
for block in self.canvas.blocks:
if self.fkt == block.fkt:
self.fkt = ""
break
if not self.fkt == "":
break
if self.bbox[0] <= 0: # make a swimlane # --> 078-SWIM
self.color = procpy.config.COLOR_SWIMLANE
self.bbox[0] = 0
self.bbox[2] = self.canvas.zoom_factor * procpy.config.SWIMLANE_WIDTH
if self.bbox[3]-self.bbox[1]==40: # only make different size, if the block size 40 is given;
self.bbox[1] = max(0, y - 3 * self.bbox[2]) # this indicates, that the block was not predefined by the user
self.bbox[3] = y + 3 * self.bbox[2] # but it is defined for the first time (not save/open)
# <-- 078-SWIM
for block in self.canvas.blocks: # check whether there is a proper space for the swimlane
if block.shape == "a":
if block.bbox[3] < y:
self.bbox[1] = max(self.bbox[1],block.bbox[3])
elif block.bbox[1] > y:
self.bbox[3] = min(self.bbox[3],block.bbox[1])
else:
self.not_valid = 1 # Clickpoint is inside of an existing swimlane
return()
self.fit_content("a")
else:
self.fit_content("x")
#************************************************************************
def sync_variables_to_text (self,varslist,varsorder):
blockvars = {}
maxv = 0
for v in varslist: # check all variables of the block object
if re.search(r"^(BLOCK|pars|JUMP|_FKT_)$",v):
continue
varskey = v
for v1 in varsorder: # special ordering
if v.find(v1) == 0:
varskey = "AAAAAAAA" + v
break
blockvars[varskey] = v
maxv = max(maxv,len(v)) # align '=' at left
blockvarskeys = list(blockvars.keys())
blockvarskeys.sort()
self.text = ""
for vkey in blockvarskeys:
v = blockvars[vkey]
self.text = self.text + "$" + (v+" "*maxv)[0:maxv] + " = " + str(obj.__dict__[v]) + "\n"
#************************************************************************
def sync_text_to_varslist (self,text=None):
if not text:
text = self.text
varslist = re.sub(r"[\n ]*([a-zA-Z\_][a-zA-Z0-9\_]*)[ =].*?(\n[\n ]*|$)","\\1,",text,99999999,re.DOTALL)
if re.sub(r"(^|,)[a-zA-\_][a-zA-Z0-9\_]*","",varslist,99999999,re.DOTALL) == ",":
return(varslist.split(","))
return(None)
#************************************************************************
# def sync_varslist_to_varsorder (self,varslist):
#
# varsorder = []
# var0 = ""
# for var in varslist: # Makes a sorting order array for the variables in varslist
# if var == "": # where sorting order patterns are as short as possible
# continue
# zaehler = 0
# while (0 == 0):
# zaehler = zaehler + 1
# var1 = var0[:zaehler]
# if not var0.find(var1) == 0:
# varsorder.append(var1)
# var0 = var
# break
# if var1 == var0:
# break
#
# return(varsorder)
#************************************************************************
def sync_content_to_fkt_and_text (self): # synchronize the content of the Text Area with fkt and text
if not 'content' in vars(self):
return(0)
fkt = self.content.get("1.0",tkinter.END)
# fkt = re.sub(r"\n([a-zA-Z])","\n\\1",fkt,re.DOTALL,99999999) # seems to be superfluous
text = ""
m = re.search(r"^(.*?)\n(.*?) *$",fkt,flags=re.DOTALL)
if m:
fkt = m.group(1)
text = m.group(2)
if not re.search(r"^[a-zA-Z][a-zA-Z\_0-9]+$",fkt):
return(-1) # not a valid fkt
if re.search(r"\S",text):
if self.shape == "a":
return(-1) # a swimlane should only carry a fkt, text shall be empty
if not self.sync_text_to_varslist(text): # no valid program code
return(-1)
try: # check also validity as python program code
exec(text)
except:
return(-1)
self.fkt = fkt
self.text = text
return(1)
#************************************************************************
def destroy (self,destroy_arrows=True):
for elem in list(self.elems.values()):
self.graphcanvas.delete(elem)
if 'content' in vars(self):
self.content.place_forget()
del self.content
del self.contentframe
self.graphcanvas.delete(self.window)
del self.window
if destroy_arrows:
for arrow in self.arrows_in:
arrow.source_block.arrows_out.remove(arrow)
arrow.destroy()
for arrow in self.arrows_out:
arrow.target_block.arrows_in.remove(arrow)
arrow.destroy()
#************************************************************************
def scale (self,fac):
for i in (0,1,2,3):
self.bbox[i] = self.bbox[i] * fac
for arrow in self.arrows_out:
arrow.scale(fac)
self.fontsize = self.fontsize * fac
self.fit_content(self.shape)
#************************************************************************
# def zoom_text (self,fac):
#
# self.fontsize = self.fontsize * fac
# self.fit_content(self.shape)
#************************************************************************
def fit_content (self,set_shape=None):
'''
Fits all contents of the block so that all is fitted
properly into the shape.
shape not None: includes checking and reformating header and text
Shapes:
r: Normale rectangle block
s: Subprocess (rectangle)
i: Case switch (diamond with X)
f: Forking block (diamond with cross)
m: Multiple switch (diamond with star)
w: Wait Block (diamond with circle)
c: Start Block (circle)
e: End Block (circle)
a: Swim lane
'''
if set_shape:
if set_shape in "rceifmwsa": # explicit definition of block shape
shape = set_shape
else: # implicit definiton of block shape by counting
shape = { "00": "r", # in and out arrows
"01": "c",
"02": "c",
"10": "r", # e
"11": "r",
"12": "ifm",
"20": "r", # e
"21": "ws",
"22": "s" } [ str(min(len(self.arrows_in),2)) + str(min(len(self.arrows_out),2)) ]
if shape == "ifm": # split off paths: shape depends on splitting case constraints
shape = "i"
wertebereiche = []
for arrow in self.arrows_out:
text = self.graphcanvas.itemcget(arrow.text,'text')
m = re.search(r"(\d+?),?(\d*)",text)
if m:
try:
val = [int(m.group(1)),int(m.group(2))]
shape = "f"
except:
val = [int(m.group(1)),int(m.group(1))]
for val1 in wertebereiche:
if val1[1] > val[0] or val[1] > val1[0]:
shape = "m"
break
if shape == "m":
break
wertebereiche.append(val)
if shape == "ws":
shape = "w"
if self.shape in shape:
shape = self.shape
if not shape == self.shape:
self.destroy(destroy_arrows=False)
x = (self.bbox[0]+self.bbox[2])/2
y = (self.bbox[1]+self.bbox[3])/2
self.content_text = self.fkt + "\n" + self.text
if shape in "ars": # Rectangle, normal block
if not shape == self.shape: # Shape has changed
self.elems = { "SHAPE": self.graphcanvas.create_rectangle(0,0,0,0,fill=self.color) }
self.contentframe = tkinter.Frame(self.graphcanvas,background=self.color,bg=self.color,bd=0)
self.content = tkinter.Text(self.contentframe,wrap={"r":"none","s":"none","a":"char"}[shape],
borderwidth=0,insertborderwidth=0,bg=self.color,highlightcolor=self.color)
self.window = self.graphcanvas.create_window(x,y,window=self.contentframe)
self.contentframe.grid_propagate(False)
self.content.insert("0.0",self.fkt + "\n" + self.text)
self.content.config(state=tkinter.DISABLED)
if shape in "s":
self.elems['EXPAND'] = self.graphcanvas.create_rectangle(0,0,0,0,width=1)
if shape in "s":
self.elems['X1'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=1)
self.elems['X2'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=1)
if shape in "a":
self.elems['X1'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=2)
self.elems['X2'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=2)
#Solution part 2: move the swim lane behind the blocks. Part 1 in the module Gui_file.
self.graphcanvas.tag_lower(self.elems['X1'])
self.graphcanvas.tag_lower(self.elems['X2'])
# self.elems['X3'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=3)
self.content.config(font=({"r":"Arial","s":"Arial","a":"Courier New Bold"}[shape],int(self.fontsize)))
elif shape in "iwfm": # Diamond
if not shape == self.shape: # Shape has changed
self.elems = { "SHAPE": self.graphcanvas.create_polygon(0,0,0,0,0,0,0,0,fill=self.color,outline='black'),
"HEADER": self.graphcanvas.create_text(0,0,anchor=tkinter.N,text=self.fkt),
"TEXT": self.graphcanvas.create_text(0,0,anchor=tkinter.CENTER,text=self.text)
}
if shape in "im":
self.elems['CROSS1'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=3)
self.elems['CROSS2'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=3)
if shape in "fm":
self.elems['X1'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=3)
self.elems['X2'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=3)
if shape == "w":
self.elems['CIRCLE'] = self.graphcanvas.create_oval(0,0,0,0,outline='black',width=3)
self.graphcanvas.itemconfig(self.elems['HEADER'],font=('Arial',int(self.fontsize)))
self.graphcanvas.itemconfig(self.elems['TEXT'], font=('Arial',int(self.fontsize)))
elif shape in "ce": # Circle
if not shape == self.shape: # Shape has changed
self.elems = { "SHAPE": self.graphcanvas.create_oval(0,0,0,0,fill=self.color,outline='black') }
self.contentframe = tkinter.Frame(self.graphcanvas,background=self.color,bg=self.color)
self.content = tkinter.Text(self.contentframe,wrap="none",bg=self.color,
highlightcolor=self.color,borderwidth=0,insertborderwidth=0)
self.window = self.graphcanvas.create_window(158,99,window=self.contentframe)
self.contentframe.grid_propagate(False)
self.content.insert("0.0",self.fkt + "\n" + self.text)
self.content.config(state=tkinter.DISABLED)
self.content.config(font=('Arial',int(self.fontsize)))
elif shape in "t": # Triangle
if not shape == self.shape: # Shape has changed
self.elems = { "SHAPE": self.graphcanvas.create_polygon(0,0,0,0,0,0,fill=self.color,outline='black') }
self.content = tkinter.Text(self.graphcanvas,wrap="none",bg=self.color,highlightcolor=self.color,
borderwidth=0,insertborderwidth=0)
self.content.insert("0.0",self.fkt + "\n" + self.text)
self.content.config(state=tkinter.DISABLED)
self.content.config(font=('Arial',int(self.fontsize)))
if not shape == self.shape: # Shape has changed
self.shape = shape
if 'content' in vars(self):
self.content.bind("<ButtonPress-1>", lambda event: self.press_button(event))
self.content.bind("<ButtonRelease-1>", self.release_button_event)
self.content.bind("<B1-Motion>", self.move_mouse_event)
self.content.bind("<Double-Button-1>", self.double_click_button_event)
for elem in list(self.elems.values()):
self.graphcanvas.tag_bind(elem,"<ButtonPress-1>", lambda event: self.press_button_event(event))
self.graphcanvas.tag_bind(elem,"<ButtonRelease-1>", self.release_button_event)
self.graphcanvas.tag_bind(elem,"<B1-Motion>", self.move_mouse_event)
self.graphcanvas.tag_bind(elem,"<Double-Button-1>", self.double_click_button_event)
x = (self.bbox[0]+self.bbox[2])/2
y = (self.bbox[1]+self.bbox[3])/2
w = self.bbox[2] - self.bbox[0]
h = self.bbox[3] - self.bbox[1]
if self.shape in "iwfmce": # reduce the bounding box to a square
if w > h: # because diamond shapes shall be always rectangular,
self.bbox[0] = x - h/2 # and circles should be circles, not ovals
self.bbox[2] = x + h/2
w = h
else:
self.bbox[1] = y - w/2
self.bbox[3] = y + w/2
h = w
if self.shape in "ars":
self.graphcanvas.coords(self.elems['SHAPE'], self.bbox[0],self.bbox[1],self.bbox[2],self.bbox[3])
self.contentframe.config(width=int(0.9*w),height=int(0.9*h))
self.content.place(x=0,y=0,width=int(0.9*w),height=int(0.9*h))
(x1,y1) = self.graphcanvas.coords(self.window)
self.graphcanvas.move(self.window,x-x1,y-y1)
if self.shape == "s":
self.graphcanvas.coords(self.elems['EXPAND'], x-0.09*w,y+0.32*h,x+0.09*w,y+0.5*h)
self.graphcanvas.coords(self.elems['X1'], x-0.09*w,y+0.32*h,x+0.09*w,y+0.32*h)
self.graphcanvas.coords(self.elems['X2'], x,y+0.4*h,x,y+0.5*h)
if self.shape == "a":
self.graphcanvas.coords(self.elems['X1'], x-0.5*w,y-0.5*h,99999999,y-0.5*h)
#self.graphcanvas.coords(self.elems['X2'], x-0.5*w,y+0.5*h,99999999,y+0.5*h)
self.graphcanvas.coords(self.elems['X2'], x-0.5*w,y+0.5*h,99,y+0.5*h)
# self.graphcanvas.coords(self.elems['X3'], x-0.5*w,y-0.5*h,x-0.5*w,y+0.5*h)
elif self.shape in "iwfm":
self.graphcanvas.coords(self.elems['SHAPE'], self.bbox[0],y,x,self.bbox[1],self.bbox[2],y,x,self.bbox[3])
self.graphcanvas.coords(self.elems['HEADER'],x,self.bbox[1])
self.graphcanvas.coords(self.elems['TEXT'], x,y)
if self.shape in "im":
self.graphcanvas.coords(self.elems['CROSS1'], x-0.17*w,y-0.17*h,x+0.17*w,y+0.17*h)
self.graphcanvas.coords(self.elems['CROSS2'], x+0.17*w,y-0.17*h,x-0.17*w,y+0.17*h)
if self.shape in "fm":
self.graphcanvas.coords(self.elems['X1'], x-0.17*w,y,x+0.17*w,y)
self.graphcanvas.coords(self.elems['X2'], x,y-0.17*h,x,y+0.17*h)
if self.shape == "w":
self.graphcanvas.coords(self.elems['CIRCLE'], x-0.19*w,y-0.19*h,x+0.19*w,y+0.19*h)
elif self.shape in "ce":
self.graphcanvas.coords(self.elems['SHAPE'], self.bbox[0],self.bbox[1],self.bbox[2],self.bbox[3])
self.contentframe.config(width=int(0.7*w),height=int(0.7*h))
self.content.place(x=0,y=0,width=int(0.7*w),height=int(0.7*h))
(x1,y1) = self.graphcanvas.coords(self.window)
self.graphcanvas.move(self.window,x-x1,y-y1)
elif self.shape in "t":
self.graphcanvas.coords(self.elems['SHAPE'], self.bbox[0],self.bbox[3],x,self.bbox[1],self.bbox[2],self.bbox[3])
self.content.place(x=int(x-0.28*w),y=int(y-0.28*h),width=int(0.56*w),height=int(0.56*h))
for arrow in self.arrows_in + self.arrows_out:
arrow.fit_block_connections()
arrow.fit_description()
if set_shape:
if set_shape in "rceifmwsa": # explicit definition of block shape
shape = set_shape
else: # implicit definiton of block shape by counting
shape = { "00": "r", # in and out arrows
"01": "c",
"02": "c",
"10": "r", # e
"11": "r",
"12": "ifm",
"20": "r", # e
"21": "ws",
"22": "s" } [ str(min(len(self.arrows_in),2)) + str(min(len(self.arrows_out),2)) ]
if shape == "ifm": # split off paths: shape depends on splitting case constraints
shape = "i"
wertebereiche = []
for arrow in self.arrows_out:
text = self.graphcanvas.itemcget(arrow.text,'text')
m = re.search(r"(\d+?),?(\d*)",text)
if m:
try:
val = [int(m.group(1)),int(m.group(2))]
shape = "f"
except:
val = [int(m.group(1)),int(m.group(1))]
for val1 in wertebereiche:
if val1[1] > val[0] or val[1] > val1[0]:
shape = "m"
break
if shape == "m":
break
wertebereiche.append(val)
if shape == "ws":
shape = "w"
if self.shape in shape:
shape = self.shape
if not shape == self.shape:
self.destroy(destroy_arrows=False)
x = (self.bbox[0]+self.bbox[2])/2
y = (self.bbox[1]+self.bbox[3])/2
self.content_text = self.fkt + "\n" + self.text
if shape in "ars": # Rectangle, normal block
if not shape == self.shape: # Shape has changed
self.elems = { "SHAPE": self.graphcanvas.create_rectangle(0,0,0,0,fill=self.color) }
self.contentframe = tkinter.Frame(self.graphcanvas,background=self.color,bg=self.color)
self.content = tkinter.Text(self.contentframe,wrap={"r":"none","s":"none","a":"char"}[shape],
bg=self.color,highlightcolor=self.color,borderwidth=0,insertborderwidth=0)
self.window = self.graphcanvas.create_window(x,y,window=self.contentframe)
self.contentframe.grid_propagate(False)
self.content.insert("0.0",self.fkt + "\n" + self.text)
self.content.config(state=tkinter.DISABLED)
if shape in "s":
self.elems['EXPAND'] = self.graphcanvas.create_rectangle(0,0,0,0,width=1)
if shape in "s":
self.elems['X1'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=1)
self.elems['X2'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=1)
if shape in "a":
self.elems['X1'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=2)
self.elems['X2'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=2)
#Solution part 2: move the swim lane behind the blocks. Part 1 in the module Gui_file.
self.graphcanvas.tag_lower(self.slems['X1'])
self.graphcanvas.tag_lower(self.slems['X2'])
# self.elems['X3'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=3)
self.content.config(font=({"r":"Arial","s":"Arial","a":"Courier New Bold"}[shape],int(self.fontsize)))
elif shape in "iwfm": # Diamond
if not shape == self.shape: # Shape has changed
self.elems = { "SHAPE": self.graphcanvas.create_polygon(0,0,0,0,0,0,0,0,fill=self.color,outline='black'),
"HEADER": self.graphcanvas.create_text(0,0,anchor=tkinter.N,text=self.fkt),
"TEXT": self.graphcanvas.create_text(0,0,anchor=tkinter.CENTER,text=self.text)
}
if shape in "im":
self.elems['CROSS1'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=3)
self.elems['CROSS2'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=3)
if shape in "fm":
self.elems['X1'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=3)
self.elems['X2'] = self.graphcanvas.create_line(0,0,0,0,fill='black',width=3)
if shape == "w":
self.elems['CIRCLE'] = self.graphcanvas.create_oval(0,0,0,0,outline='black',width=3)
self.graphcanvas.itemconfig(self.elems['HEADER'],font=('Arial',int(self.fontsize)))
self.graphcanvas.itemconfig(self.elems['TEXT'], font=('Arial',int(self.fontsize)))
elif shape in "ce": # Circle
if not shape == self.shape: # Shape has changed
self.elems = { "SHAPE": self.graphcanvas.create_oval(0,0,0,0,fill=self.color,outline='black') }
self.contentframe = tkinter.Frame(self.graphcanvas,background=self.color,bg=self.color)
self.content = tkinter.Text(self.contentframe,wrap="none",bg=self.color,
highlightcolor=self.color,borderwidth=0,insertborderwidth=0)
self.window = self.graphcanvas.create_window(158,99,window=self.contentframe)
self.contentframe.grid_propagate(False)
self.content.insert("0.0",self.fkt + "\n" + self.text)
self.content.config(state=tkinter.DISABLED)
self.content.config(font=('Arial',int(self.fontsize)))
elif shape in "t": # Triangle
if not shape == self.shape: # Shape has changed
self.elems = { "SHAPE": self.graphcanvas.create_polygon(0,0,0,0,0,0,fill=self.color,outline='black') }
self.content = tkinter.Text(self.graphcanvas,wrap="none",bg=self.color,highlightcolor=self.color,
borderwidth=0,insertborderwidth=0)
self.content.insert("0.0",self.fkt + "\n" + self.text)
self.content.config(state=tkinter.DISABLED)
self.content.config(font=('Arial',int(self.fontsize)))
if not shape == self.shape: # Shape has changed
self.shape = shape
if 'content' in vars(self):
self.content.bind("<ButtonPress-1>", lambda event: self.press_button(event))
self.content.bind("<ButtonRelease-1>", self.release_button)
self.content.bind("<B1-Motion>", self.move_mouse)
self.content.bind("<Double-Button-1>", self.double_click_button)
for elem in list(self.elems.values()):
self.graphcanvas.tag_bind(elem,"<ButtonPress-1>", lambda event: self.press_button(event))
self.graphcanvas.tag_bind(elem,"<ButtonRelease-1>", self.release_button)
self.graphcanvas.tag_bind(elem,"<B1-Motion>", self.move_mouse)
self.graphcanvas.tag_bind(elem,"<Double-Button-1>", self.double_click_button)
x = (self.bbox[0]+self.bbox[2])/2
y = (self.bbox[1]+self.bbox[3])/2
w = self.bbox[2] - self.bbox[0]
h = self.bbox[3] - self.bbox[1]
if self.shape in "iwfmce": # reduce the bounding box to a square
if w > h: # because diamond shapes shall be always rectangular,
self.bbox[0] = x - h/2 # and circles should be circles, not ovals
self.bbox[2] = x + h/2
w = h
else:
self.bbox[1] = y - w/2
self.bbox[3] = y + w/2
h = w
if self.shape in "ars":
self.graphcanvas.coords(self.elems['SHAPE'], self.bbox[0],self.bbox[1],self.bbox[2],self.bbox[3])
self.contentframe.config(width=int(0.9*w),height=int(0.9*h))
self.content.place(x=0,y=0,width=int(0.9*w),height=int(0.9*h))
(x1,y1) = self.graphcanvas.coords(self.window)
self.graphcanvas.move(self.window,x-x1,y-y1)
if self.shape == "s":
self.graphcanvas.coords(self.elems['EXPAND'], x-0.09*w,y+0.32*h,x+0.09*w,y+0.5*h)
self.graphcanvas.coords(self.elems['X1'], x-0.09*w,y+0.32*h,x+0.09*w,y+0.32*h)
self.graphcanvas.coords(self.elems['X2'], x,y+0.4*h,x,y+0.5*h)
if self.shape == "a":
self.graphcanvas.coords(self.elems['X1'], x-0.5*w,y-0.5*h,99999999,y-0.5*h)
self.graphcanvas.coords(self.elems['X2'], x-0.5*w,y+0.5*h,99999999,y+0.5*h)
# self.graphcanvas.coords(self.elems['X3'], x-0.5*w,y-0.5*h,x-0.5*w,y+0.5*h)
elif self.shape in "iwfm":
self.graphcanvas.coords(self.elems['SHAPE'], self.bbox[0],y,x,self.bbox[1],self.bbox[2],y,x,self.bbox[3])
self.graphcanvas.coords(self.elems['HEADER'],x,self.bbox[1])
self.graphcanvas.coords(self.elems['TEXT'], x,y)
if self.shape in "im":
self.graphcanvas.coords(self.elems['CROSS1'], x-0.17*w,y-0.17*h,x+0.17*w,y+0.17*h)
self.graphcanvas.coords(self.elems['CROSS2'], x+0.17*w,y-0.17*h,x-0.17*w,y+0.17*h)
if self.shape in "fm":
self.graphcanvas.coords(self.elems['X1'], x-0.17*w,y,x+0.17*w,y)
self.graphcanvas.coords(self.elems['X2'], x,y-0.17*h,x,y+0.17*h)
if self.shape == "w":
self.graphcanvas.coords(self.elems['CIRCLE'], x-0.19*w,y-0.19*h,x+0.19*w,y+0.19*h)
elif self.shape in "ce":
self.graphcanvas.coords(self.elems['SHAPE'], self.bbox[0],self.bbox[1],self.bbox[2],self.bbox[3])
self.contentframe.config(width=int(0.7*w),height=int(0.7*h))
self.content.place(x=0,y=0,width=int(0.7*w),height=int(0.7*h))
(x1,y1) = self.graphcanvas.coords(self.window)
self.graphcanvas.move(self.window,x-x1,y-y1)
elif self.shape in "t":
self.graphcanvas.coords(self.elems['SHAPE'], self.bbox[0],self.bbox[3],x,self.bbox[1],self.bbox[2],self.bbox[3])
self.content.place(x=int(x-0.28*w),y=int(y-0.28*h),width=int(0.56*w),height=int(0.56*h))
for arrow in self.arrows_in + self.arrows_out:
arrow.fit_block_connections()
arrow.fit_description()
#************************************************************************
def sync_content_to_text_and_header (self):
if 'content' in vars(self):
header = self.content.get("1.0",tkinter.END)
text = ""
m = re.search(r"^(.*?)\n(.*)$",header,re.DOTALL)
if m:
header = m.group(1)
text = m.group(2)
if not re.search(r"^[a-z][a-zA-Z\_0-9]+$",header):
return(-1) # not a valid header
try:
exec(text)
except:
return(-1) # no valid program code
self.header = header
self.text = text
return(1) # self.content successful synced
return(0) # no self.content variable
#************************************************************************
def get_shape_connection_point (self,p1):
'''
Computes the point on the the border of the surrounding shape of the block
which connects an outer point p to the block
'''
p = [ min(max(self.bbox[0], p1[0]), self.bbox[2]), min(max(self.bbox[1], p1[1]), self.bbox[3]) ]
# p2: touches the bounding box. This basic point has to be extended into the bounding box depending on the shape:
if not self.shape in "rs":
x = (self.bbox[0]+self.bbox[2])/2
y = (self.bbox[1]+self.bbox[3])/2
p2 = p[:]
if p2[0] == p1[0]:
p2[1] = y
if p2[1] == p1[1]:
p2[0] = x
if self.shape in "iwfm": # diamond
fac = 1
if p1[0] < x:
p3 = [self.bbox[0],y]
else:
p3 = [self.bbox[2],y]
fac = -fac
if p1[1] < y:
p4 = [x,self.bbox[1]]
else:
p4 = [x,self.bbox[3]]
fac = -fac
try:
m = ( p4[0] - p2[0] + fac * (p4[1] - p2[1]) ) / ( p1[0] - p2[0] + fac * (p1[1] - p2[1]) )
p = [ p1[0] * m + p2[0] * (1-m), p1[1] * m + p2[1] * (1-m) ]
except: # in this case, the outer point points to the closest edge
pass
elif self.shape in "ce": # circle
a = (p1[0]-p2[0])**2 + (p1[1]-p2[1])**2 # a * m*m - 2 * b * m + c = 0, quadratic equation to solve
b = (p1[0]-p2[0])*(x-p2[0]) + (p1[1]-p2[1])*(y-p2[1])
c = (x-p2[0])**2 + (y-p2[1])**2 - ((self.bbox[0]-self.bbox[2])/2)**2
try:
m = ( b + (b**2 - a*c)**0.5 ) / a
p = [ p1[0] * m + p2[0] * (1-m), p1[1] * m + p2[1] * (1-m) ]
except: # in this case, the outer point points to the most west, east, north or south point of the circle
pass
elif self.shape in "t": # triangle
if p1[1] > self.bbox[3]: # point is underneath the bottom of the triangle.
pass # Nothing to do -> the same behaviour as in rectangle shape mode
else:
p3 = [x,self.bbox[1]]
if p1[0] < x:
p4 = [self.bbox[0],self.bbox[3]]
else:
p4 = [self.bbox[2],self.bbox[3]]
a = (p2[0]-p4[0])*(p3[1]-p4[1]) - (p2[1]-p4[1])*(p3[0]-p4[0])
b = (p2[0]-p1[0])*(p3[1]-p4[1]) - (p2[1]-p1[1])*(p3[0]-p4[0])
try:
m = a / b
p = [ p1[0] * m + p2[0] * (1-m), p1[1] * m + p2[1] * (1-m) ]
except: # in this case, the outer point points to the closest edge
pass
return(p)
#************************************************************************
def gridpos (self,i=None,j=None):
# if 'newbbox' in vars(self):
# return(tuple(self.ij))
px = (1-self.canvas.snap['OBJX']) * self.bbox[0] + self.canvas.snap['OBJX'] * self.bbox[2]
py = (1-self.canvas.snap['OBJY']) * self.bbox[1] + self.canvas.snap['OBJY'] * self.bbox[3]
if not i:
i = int((px - self.canvas.griddata['OFFSETX'] + (0.5+self.canvas.snap['GRIDX'])*self.canvas.griddata['X'])/self.canvas.griddata['X'])
j = int((py - self.canvas.griddata['OFFSETY'] + (0.5+self.canvas.snap['GRIDY'])*self.canvas.griddata['Y'])/self.canvas.griddata['Y'])
x = self.canvas.griddata['OFFSETX'] + (i + self.canvas.snap['GRIDX']) * self.canvas.griddata['X']
y = self.canvas.griddata['OFFSETY'] + (j + self.canvas.snap['GRIDY']) * self.canvas.griddata['Y']
if self.shape == "a":
self.newbbox = self.bbox[:]
else:
self.newbbox = [ self.bbox[0] + (x-px), self.bbox[1] + (y-py), self.bbox[2] + (x-px), self.bbox[3] + (y-py) ]
self.ij = [i,j]
return(i,j)
#************************************************************************
def get_varlen (self):
'''
Gives the maximal length of variable names.
Given as a value lower than 0 if no arrows exist where
the block is target. E.g. if the block is the starting node.
'''
maxv = 5
for textline in self.graphcanvas.itemcget(self.text,'text').split("\n"):
m = re.search(r"^(.*?)[ \=]",textline)
if m:
maxv = max(maxv,len(m.group(1)))
if not self.arrows_out:
maxv = -maxv
return(maxv)
#************************************************************************
def get_vars (self):
'''
Gives the variables with their actual values.
'''
block = [ self.graphcanvas.itemcget(self.fkt,'text') ] #hier stand: self.header collecting block informations
m = re.search(r"^ *(.*?)( *\/ *)(.*?) *$",block[0])
if m:
block = [ m.group(1), m.group(3) ]
coords = self.bbox
block.append( "%3.1f" % ((coords[0]+coords[2])/2) )
block.append( "%3.1f" % ((coords[1]+coords[3])/2) )
block.append( "%3.1f" % (coords[2]-coords[0]) )
block.append( "%3.1f" % (coords[3]-coords[1]) )
varsval = [ ['BLOCK',block] ]
varsval1 = {} # collecting other visible variables
for textline in self.graphcanvas.itemcget(self.text,'text').split("\n"):
m = re.search(r"^(.*?)( *\= *)(.*?) *$",textline)
if m:
varsval1[m.group(1)] = m.group(3)
varsval1_keys = list(varsval1.keys())
varsval1_keys.sort()
for item in varsval1_keys:
varsval.append([item,varsval1[item]])
jump = {} # collecting infos where to jump:
for arrow in self.arrows_out:
jumpinfo = [ self.graphcanvas.itemcget(arrow.text,'text') ]
for arrowline in arrow.arrowlines[1:]:
for c in self.graphcanvas.coords(arrowline)[:2]:
jumpinfo.append("%3.1f" % c)
jump[arrow.target_block] = jumpinfo
varsval.append( ['JUMP',jump] )
return(varsval)
#************************************************************************
def bounding_box (self,extbox=None):
'''
Returns the bounding box of the block.
If an optional 4-elem array is given, this
will be extended to the bounding box.
'''
if extbox == None:
extbox = []
if len(extbox) == 0:
extbox.append(self.bbox[0])
extbox.append(self.bbox[1])
extbox.append(self.bbox[2])
extbox.append(self.bbox[3])
else:
extbox[0] = min(extbox[0],self.bbox[0])
extbox[1] = min(extbox[1],self.bbox[1])
extbox[2] = max(extbox[2],self.bbox[2])
extbox[3] = max(extbox[3],self.bbox[3])
return(extbox)
#************************************************************************
def press_button (self,event=[]):
if type(event) == type([]): # Testschnittstelle
try:
self.x0 = event[0]
except:
self.x0 = self.bbox[0] + self.bbox[2]/2
try:
self.y0 = event[1]
except:
self.y0 = self.bbox[1] + self.bbox[3]/2
(self.x1,self.y1) = (self.x0,self.y0)
else:
(self.x0,self.y0) = (event.x,event.y)
(self.x1,self.y1) = (event.x_root,event.y_root)
self.graphcanvas.configure(cursor='sizing') # Alternative mouse pointers: arrow circle
# clock cross dotbox exchange fleur heart
self.resize_box = "" # man mouse pirate plus shuttle sizing spider
self.move_blocks = [] # spraycan star target tcross trek watch
self.move_arrows = {}
self.move_arrowlines_start = {}
self.move_arrowlines_end = {}
self.bbox_press = self.bbox[:]
self.w = self.bbox[2] - self.bbox[0]
self.h = self.bbox[3] - self.bbox[1]
if self.shape in "ars":
if abs(self.y0 - self.bbox[3]) < 4: # if pressing point is near the border of the box
self.resize_box = self.resize_box + "S" # mark the direction for resizing
if abs(self.y0 - self.bbox[1]) < 4:
self.resize_box = self.resize_box + "N"
if self.shape in "rs":
if abs(self.x0 - self.bbox[0]) < 4:
self.resize_box = self.resize_box + "W"
if abs(self.x0 - self.bbox[2]) < 4:
self.resize_box = self.resize_box + "E"
if self.resize_box == "" and self.shape == "a": # Shifting a swimlane means also shifting all blocks in its area
(self.move_blocks,self.move_arrows,self.move_arrowpoints) = self.blocks_and_arrows_in_swimlane()
for block in self.canvas.blocks:
if not self == block and block.shape == "a":
(block.move_blocks,block.move_arrows,block.move_arrowpoints) = block.blocks_and_arrows_in_swimlane()
self.last_event = 1
return "break"
#**********************************************************
def blocks_and_arrows_in_swimlane (self,mode=0): # Returns the blocks which are in the swimlane if i am swimlane
erg = []
for block in self.canvas.blocks:
if self.bbox[1] <= block.bbox[1] <= self.bbox[3]:
if not block.shape == "a":
erg.append(block)
arrows = []
for block in erg:
for arrow in block.arrows_in:
if arrow.source_block in erg:
arrows.append(arrow)
if mode > 0:
return(arrows)
exclude_arrows = self.arrows_covered_by_some_swimlane()
singlepoints = []
for block in self.canvas.blocks:
for arrow in block.arrows_in:
if not arrow in exclude_arrows:
zaehler = 0
for arrowline in arrow.arrowlines:
coords = self.graphcanvas.coords(arrowline)
for i in (0,2):
if self.bbox[1] <= coords[i+1] <= self.bbox[3]:
singlepoints.append([arrow,zaehler,i])
zaehler = zaehler + 1
return(erg,arrows,singlepoints)
#**********************************************************
def arrows_covered_by_some_swimlane (self):
erg = []
for swimlane in self.canvas.blocks:
if swimlane.shape == "a":
erg = erg + swimlane.blocks_and_arrows_in_swimlane(1)
pass
return(erg)
#**********************************************************
def blocks_in_swimlane (self,mode=0): # Returns the blocks which are in the swimlane if self is a swimlane
if not self.shape == "a":
return([])
erg = { 'BLOCKS': [], # Blocks in the swimlane
'ARROWLINES_BEGIN': {}, # Starting arrow lines in the swimlane
'ARROWLINES_END' : {}, # Ending arrow lines in the swimlane
'ARROWS' : {} } # Arrows from one block in the swimlane to another
sub_swimlanes = []
for block in self.canvas.blocks:
if self.bbox[1] <= block.bbox[1] <= self.bbox[3]:
if self.bbox[0] <= block.bbox[0]:
if not block.shape == "a":
erg['BLOCKS'].append(block)
elif not block == self and ( not self.bbox[0] == block.bbox[0] or
self.bbox[1] < block.bbox[1] or
( self.bbox[1] == block.bbox[1] and self.bbox[3] < block.bbox[3] ) ):
sub_swimlanes.append(block)
for block in erg['BLOCKS']:
for arrow in block.arrows_in + block.arrows_out:
erg['ARROWS'][arrow] = 1
for arrowline in arrow.arrowlines:
coords = self.graphcanvas.coords(arrowline)
bed1 = arrow in block.arrows_in and arrow.source_block in self.move_blocks
bed2 = arrow in block.arrows_out and arrow.target_block in self.move_blocks
if bed1 or bed2 or self.bbox[1] < coords[1] and coords[1] < self.bbox[3]:
erg['ARROWLINES_BEGIN'][arrowline] = 1
if bed1 or bed2 or self.bbox[1] < coords[3] and coords[3] < self.bbox[3]:
erg['ARROWLINES_END'][arrowline] = 1
for arrow in block.arrows_out:
erg['ARROWLINES_BEGIN'][arrow.arrowlines[0]] = 1
for arrow in block.arrows_in:
erg['ARROWLINES_END'][arrow.arrowlines[-1]] = 1
return(erg)
self.last_event = 1
#**********************************************************
def double_click_button (self,event):
(self.x0,self.y0) = (event.x,event.y)
(self.x1,self.y1) = (event.x_root,event.y_root)
self.last_event = 2
return "break"
#****************************************************
def release_button (self,event=None):
if (abs(self.bbox[0] - self.bbox_press[0]) + abs(self.bbox[1] - self.bbox_press[1]) +
abs(self.bbox[2] - self.bbox_press[2]) + abs(self.bbox[3] - self.bbox_press[3]) > 10):
self.last_event = 4
if self.shape == "a" and self.last_event ==3: #before: in (3,4): old version creates error with changing size of the swimlane
self.canvas.rearr_swimlane(0.2)
if self.last_event in (1,3):
self.resize_box = ""
self.graphcanvas.configure(cursor='arrow')
if self.canvas.hl_block == self:
self.syntax_error = 0
if not self.canvas.hl_block == None:
if self.canvas.hl_block.sync_content_to_fkt_and_text() == -1:
if not self.canvas.hl_block == self:
self.canvas.hl_block.syntax_error = 1
return()
self.canvas.hl_block.syntax_error = 0
bed = None
if not self.canvas.hl_block == self: # if I am not yet highlighted, un-highlight the former highlighted block
self.canvas.hl_block_0 = self.canvas.hl_block # and set it to the last highlighted block,
self.canvas.hl_block = self # and set myself to highlighted
self.hl_arrow = None
for arrow in self.arrows_in: # now check all incoming arrows. The one where its
if arrow.source_block == self.canvas.hl_block_0: # source_block is the last highlighted block,
self.hl_arrow = arrow # has also to be highlighted
if False and self.hl_arrow == None: ## DISABLED # check also inverted direction
for arrow in self.arrows_out:
if arrow.target_block == self.canvas.hl_block_0:
self.hl_arrow = arrow
self.highlight_block(0)
else:
self.syntax_error = 0
elif self.last_event == 2: # last event was a double click
self.canvas.create_arrow()
elif self.canvas.griddata['SNAP']:
self.canvas.rearr_grid(0.2)
else:
self.canvas.rearr_grid(0.2,1)
self.last_event = 1
return "break"
#****************************************************
def highlight_block (self,nr,mode=0): # mode == 1: blinking
fillcolor1 = [procpy.config.COLOR_HIGHLIGHT_ALT[0],procpy.config.COLOR_HIGHLIGHT_ALT[0],
procpy.config.COLOR_HIGHLIGHT[0],procpy.config.COLOR_HIGHLIGHT[0]
][nr+mode]
self.graphcanvas.itemconfig(self.elems['SHAPE'],fill=fillcolor1)
if 'content' in vars(self):
self.content.config(bg=fillcolor1,highlightcolor=fillcolor1)
self.contentframe.config(background=fillcolor1,bg=fillcolor1,highlightcolor=fillcolor1)
if self.hl_arrow:
fillcolor2 = [procpy.config.COLOR_HIGHLIGHT[0],self.color,self.color,self.color][nr+mode]
if len(self.canvas.blocks) < 6:
# fillcolor2 = fillcolor1
fillcolor2 = procpy.config.COLOR_HIGHLIGHT[0]
self.hl_arrow.highlight(fillcolor2)
else:
if 'content' in vars(self):
if self.content.cget('state') == tkinter.DISABLED:
self.content.config(state=tkinter.NORMAL)
self.content.focus_set()
self.content.mark_set("insert",tkinter.END)
if self.sync_content_to_fkt_and_text() == -1:
self.syntax_error = 1
else:
self.syntax_error = 0
delay = -nr
if self.canvas.hl_block == self:
delay = 180 + mode*120
if delay > -1:
self.canvas.loopobj.after(delay,self.highlight_block,1-nr,2*self.syntax_error)
else:
self.graphcanvas.itemconfig(self.elems['SHAPE'],fill=self.color)
if 'content' in vars(self):
self.content.config(bg=self.color,highlightcolor=self.color)
self.contentframe.config(background=self.color,bg=self.color,highlightcolor=self.color)
if self.hl_arrow:
self.hl_arrow.highlight()
self.hl_arrow = None
if 'content' in vars(self):
self.content.config(state=tkinter.DISABLED)
#************************************************************************
def move_mouse (self,event):
dx = event.x_root - self.x1
dy = event.y_root - self.y1
self.last_event = 3
if self.resize_box == "":
self.move(dx,dy)
else:
self.resize(dx,dy)
self.x1 = event.x_root
self.y1 = event.y_root
return "break"
#****************************************************
def xxmove (self,dx,dy):
if ( self.bbox[0]+dx < 0 or False and self.bbox[2]+dx > self.graphcanvas.winfo_width() or
self.bbox[1]+dy < 0 or False and self.bbox[3]+dy > self.graphcanvas.winfo_height() ) :
return() # keine gute Loesung, um zu verhindern, dass die Objekte aus dem Zeichenbereich
# gehen. Insbesondere die rechte und untere Grenze wird mit dem obigen Code
# beim Scalen zu stark geschuetzt. Hier muss eine bessere Loesung her. Am besten
# waere es, den Mauszeiger auf das Gebiet des graphcanvas zu beschraenken, das scheint
# aber schwierig zu sein. --> task_001
if self.shape == "a":
bed = False
depending_swimlane = None # the depending swimlane also to have been moved (when a block or ancesters block is highlighted)
for swimlane in self.canvas.swimlanes:
if swimlane == self or not swimlane.shape == "a":
continue
if (swimlane.bbox[1] < self.bbox[1] < swimlane.bbox[3] or swimlane.bbox[1] < self.bbox[3] < swimlane.bbox[3]
or self.bbox[1] < swimlane.bbox[1] < self.bbox[3] or self.bbox[1] < swimlane.bbox[3] < self.bbox[3]):
if move_as_a_depending_swimlane or self == self.canvas.hl_block:
if (swimlane.bbox[1] - self.bbox[1]) * dy > 0:
if move_as_a_depending_swimlane or self == self.canvas.hl_block:
depending_swimlane = swimlane
bed = True
break
else:
bed = True # block intersection
break
if bed:
if depending_swimlane:
depending_swimlane.move(dx,dy,1)
elif self.bbox[0] == 0:
self.bbox[0] = self.bbox[0] + self.canvas.zoom_factor * procpy.config.SWIMLANE_WIDTH
self.bbox[2] = self.bbox[2] + self.canvas.zoom_factor * procpy.config.SWIMLANE_WIDTH
else:
if not self.bbox[0] == 0:
self.bbox[0] = self.bbox[0] - self.canvas.zoom_factor * procpy.config.SWIMLANE_WIDTH
self.bbox[2] = self.bbox[2] - self.canvas.zoom_factor * procpy.config.SWIMLANE_WIDTH
self.bbox[1] = self.bbox[1] + dy
self.bbox[3] = self.bbox[3] + dy
if not self.shape == "a":
self.bbox[0] = self.bbox[0] + dx
self.bbox[2] = self.bbox[2] + dx
else:
for block in self.move_blocks:
block.move(0,dy)
for arrow in self.move_arrows:
arrow.move(0,dy)
for point in self.move_arrowpoints:
arrow = point[0]
arrowline = arrow.arrowlines[point[1]]
coords = self.graphcanvas.coords(arrowline)
coords[point[2]] = coords[point[2]] + 0
coords[point[2]+1] = coords[point[2]+1] + dy
self.graphcanvas.coords(arrowline,tuple(coords))
arrow.fit_description()
self.fit_content()
#**********************************************************
def resize (self,dx,dy):
if re.search(r"N",self.resize_box):
self.bbox[1] = self.bbox[1] + dy
elif re.search(r"S",self.resize_box):
self.bbox[3] = self.bbox[3] + dy
if re.search(r"W",self.resize_box):
self.bbox[0] = self.bbox[0] + dx
elif re.search(r"E",self.resize_box):
self.bbox[2] = self.bbox[2] + dx
self.fit_content(self.shape)
for arrow in self.arrows_in + self.arrows_out:
arrow.fit_block_connections()
arrow.fit_description()
def __repr__(self):
return repr(self.arrows_in)+'-->['+repr(self.bbox)+']'+'--> '+repr(self.arrows_out)+'['+repr(self.elems)+']'
#****************************************************