def insert_toggle_dir(self, name, angle=0): object = Autoshape(name) object.Transform(Rotation(angle * pi / 180.)) object.ToggleDir() self.main_window.PlaceObject(object)
def getStructBoxnode(inlabel, plist, vlist): global courfont global tarrw1, tarrw2, tarrw3 pvfnsz = 12 # font size for pointers/vars # here we'll also generate a dict of all graphic objects # global 'id' is not needed - it will be a part of a tuple, along with master group sbdict = {} ## pointers - horizontal yoff = 0 ypad = 2 lastcharpad = pvfnsz # so the arrow dont overlap with last char xoutermost = 0 # to get the longest arrow (so we use it to make arrows same length) point_tflist = [] # list of actual textfield objects tcount = 0 for iptxt in plist: textfld = SimpleText(Translation(0, yoff), iptxt) textfld.SetProperties(font=courfont, font_size=pvfnsz) textfld.update_rects() sbdict['ptf_' + str(tcount)] = textfld # add connector line tfbr = textfld.bounding_rect tfline = getQuickLine((tfbr.left, tfbr.bottom), (tfbr.right + lastcharpad, tfbr.bottom)) tfline.SetProperties(line_width=2.0, line_arrow1=tarrw1, line_arrow2=tarrw2) tfline.update_rects() sbdict['ptfl_' + str(tcount)] = tfline if tfbr.right + lastcharpad > xoutermost: xoutermost = tfbr.right + lastcharpad # group line and text tgrp = Group([tfline, textfld]) tgrp.update_rects() sbdict['ptfg_' + str(tcount)] = tgrp # add the group - not just textfld - to list here point_tflist.append(tgrp) # get height - calc next offset; yoff will go negative, but nvm (will group and move) # don't use tgrp's BB, its too high llx, lly, urx, ury = textfld.bounding_rect # /tgrp. /getTfBB(textfld) tfHeight = ury - lly yoff -= tfHeight + ypad tcount += 1 # done - now resize all the arrows according to xoutermost, # so they are same length # SetLine(i, x, y[, cont]) "Replace the ith segment by a line segment" # where the i-th segment is the node.. for tgrp in point_tflist: # loop (in a list) tfline = tgrp.objects[ 0] # access Group (sub)object - tfline is first [0] # get 2nd node (=segment 1) - in there, Point() is third in list ([2]) tmpep = tfline.paths[0].Segment(1)[2] # change 2nd node (=segment 1) of the (first) path (paths[0]) tfline.paths[0].SetLine(1, (xoutermost, tmpep.y)) tfline.update_rects() tgrp.update_rects() # finally, group all these point_group = Group(point_tflist) # accepts list directly point_group.update_rects() sbdict['ptg'] = point_group ## variables - vertical (so, rotate group afterwards) yoff = 0 ypad = 2 lastcharpad = 1 # pvfnsz /so the arrow dont overlap with last char xoutermost = 0 # to get the longest arrow (so we use it to make arrows same length) varbl_tflist = [] # list of actual textfield objects tcount = 0 havevars = len(vlist) # could be zero! for ivtxt in vlist: textfld = SimpleText(Translation(0, yoff), ivtxt) textfld.SetProperties(font=courfont, font_size=pvfnsz) textfld.update_rects() sbdict['vtf_' + str(tcount)] = textfld # add connector line tfbr = textfld.bounding_rect tfline = getQuickLine((tfbr.left, tfbr.bottom), (tfbr.right + lastcharpad, tfbr.bottom)) tfline.SetProperties(line_width=2.0, line_arrow1=tarrw1, line_arrow2=tarrw3) tfline.update_rects() sbdict['vtfl_' + str(tcount)] = tfline if tfbr.right + lastcharpad > xoutermost: xoutermost = tfbr.right + lastcharpad # group line and text tgrp = Group([tfline, textfld]) tgrp.update_rects() sbdict['vtfg_' + str(tcount)] = tgrp # add the group - not just textfld - to list here varbl_tflist.append(tgrp) # get height - calc next offset; yoff will go negative, but nvm (will group and move) llx, lly, urx, ury = textfld.bounding_rect # getTfBB(textfld) tfHeight = ury - lly yoff -= tfHeight + 2 tcount += 1 # done - now resize all the arrows according to xoutermost, # so they are same length # SetLine(i, x, y[, cont]) "Replace the ith segment by a line segment" # where the i-th segment is the node.. for tgrp in varbl_tflist: # loop (in a list) tfline = tgrp.objects[ 0] # access Group (sub)object - tfline is first [0] # get 2nd node (=segment 1) - in there, Point() is third in list ([2]) tmpep = tfline.paths[0].Segment(1)[2] # change 2nd node (=segment 1) of the (first) path (paths[0]) tfline.paths[0].SetLine(1, (xoutermost, tmpep.y)) tfline.update_rects() tgrp.update_rects() # finally, group all these varbl_group = Group(varbl_tflist) # accepts list directly varbl_group.update_rects() sbdict['vtg'] = varbl_group # rotate variable group # for repositioning - easiest to rotate around # upper-left corner (instead of center point) vgbr = varbl_group.bounding_rect varbl_g_cp = vgbr.center() # centerpoint varbl_g_ul = Point(vgbr.left, vgbr.top) # top (upper) left varbl_group.Transform(Rotation(radians(-90), varbl_g_ul)) varbl_group.update_rects() # must reassign variable for .bounding_rect # after transform and update_rects()!!: vgbr = varbl_group.bounding_rect vgbr_w = vgbr.right - vgbr.left vgbr_h = vgbr.top - vgbr.bottom # also, below needed for box & move calc: #~ point_group.update_rects() pgbr = point_group.bounding_rect pgbr_w = pgbr.right - pgbr.left pgbr_h = pgbr.top - pgbr.bottom # and note - groups seem to add some sort of padding, so align to intern lines instead (instead of group BB edges) # get first (moveto) Point of first tf's line (align to that, instead of pgbr) - needed for 'boxing' below: tfline = point_group[0].objects[0] tmpep = tfline.paths[0].Segment(0)[2] tmpep_v = Point(0, 0) if havevars != 0: tmpep_v = varbl_group[0].objects[0].paths[0].Segment(0)[2] xmoveadj = tmpep.x - pgbr.left # adjustment due to group padding ymoveadj = -(tmpep_v.y - vgbr.top) # only for moving varbl_group # move rotated varbl_group below left of point_group xmove = 0 # -vgbr_w # looks ok like this xmove += xmoveadj # adjust due to group padding ymove = -pgbr_h ymove += ymoveadj # adjust due to group padding varbl_group.Translate(Point(xmove, ymove)) varbl_group.update_rects() vgbr = varbl_group.bounding_rect ## add the box label lxpad = 10 # box label x padding tfld_label = SimpleText(Translation(0, 0), inlabel) tfld_label.SetProperties(font=courfont, font_size=16) tfld_label.update_rects() # reposition # on y: center align tfld_label with center of point_group cp_pg = pgbr.center() tlbr = tfld_label.bounding_rect cp_tl = tlbr.center() ymove = -(cp_tl.y - cp_pg.y) # on x: <NO>align right edge of tfld_label + pad with left edge of point_group</NO> # center in respect to expected boxwidth instead # calc expected boxwidth first tlbr = tfld_label.bounding_rect tlbr_w = tlbr.right - tlbr.left boxwidth = lxpad + tlbr_w + lxpad # only title text label width + padding varbl_width = vgbr.right - vgbr.left if boxwidth < lxpad + varbl_width + lxpad: boxwidth = lxpad + varbl_width + lxpad #~ xmove = -(tlbr.right + lxpad - pgbr.left) # title text left aligned w/ right edge xmove = -((tlbr.center().x - pgbr.left) + boxwidth / 2) xmove += xmoveadj # adjust due to group padding tfld_label.Translate(Point(xmove, ymove)) tfld_label.update_rects() tlbr = tfld_label.bounding_rect # must reassign variable (though we won't need it anymore) ## create a box for point/varbl_group # start at upper left point of point_group BB; # go downleft, to <NO>upper left point of varbl_group BB</NO> # .. note - groups seem to add some sort of padding, so align to intern lines: # go downleft, to upper edge of varbl_group, and ([left edge of tfld_label] - pad) # get first (moveto) Point of first tf's line (align to that, instead of pgbr) tfline = point_group[0].objects[0] tmpep = tfline.paths[0].Segment(0)[2] start_x = tmpep.x # pgbr.left start_y = pgbr.top off_x = -(boxwidth) # -vgbr_w off_y = -pgbr_h trec = Rectangle(trafo=Trafo(off_x, 0, 0, off_y, start_x, start_y)) trec.SetProperties( line_width=2.0, fill_pattern=SolidPattern(CreateRGBColor(0.7, 0.7, 0.9)), ) trec.update_rects() sbdict['box'] = trec # now group all these # grouping goes: 1st on bottom, 2nd on top of it, etc.. retgrp = Group([trec, tfld_label, point_group, varbl_group]) retgrp.update_rects() # move lower left corner of retgrp to 0,0 rgbr = retgrp.bounding_rect retgrp.Translate(Point(-rgbr.left, -rgbr.bottom)) retgrp.update_rects() return (retgrp, sbdict)