Beispiel #1
0
 def insert_toggle_dir(self, name, angle=0):
     object = Autoshape(name)
     object.Transform(Rotation(angle * pi / 180.))
     object.ToggleDir()
     self.main_window.PlaceObject(object)
Beispiel #2
0
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)