示例#1
0
class checkbox_pref(InstanceMacro):
    #e rename -- Checkbox(...), with various kinds of args to say what state it uses in different ways?
    #e make it one of several prefs controls for other types of pref and control
    #e generalize to all named state -- e.g. see also LocalVariable_StateRef -- permit passing in the stateref?
    #e get dflt label from stateref??
    # note: this was split out of kluge_dragtool_state_checkbox_expr 061214,
    # extended here into a def (later renamed checkbox_pref_OLDER), then a class
    prefs_key = Arg(str)
    label = Arg(Anything)  # string or Widget2D
    dflt = ArgOrOption(bool, False)
    sbar_text = Option(str, '')
    use_label = If(call_Expr(lambda label: type(label) == type(""), label),
                   TextRect(label), label)  ## was TextRect(label,1,20)
    use_sbar_text = or_Expr(
        sbar_text,
        If(call_Expr(lambda label: type(label) == type(""), label), label, ""))
    stateref = Instance(PrefsKey_StateRef(prefs_key, dflt))
    # note: without Instance here, next line stateref.value says (correctly):
    ## AssertionError: compute method asked for on non-Instance <PrefsKey_StateRef#47221(a)>
    var = stateref.value
    checkbox = If(
        var,
        checkbox_image('mac_checkbox_on.png'),
        checkbox_image('mac_checkbox_off.png'),
    )
    _value = DisplayListChunk(
        Highlightable(
            SimpleRow(CenterY(checkbox),
                      CenterY(use_label)),  # align = CenterY is nim
            ## on_press = Set(debug_evals_of_Expr(stateref.value), not_Expr(var) ), #070119 debug_evals_of_Expr - worked
            on_press=_self.on_press,
            # the following works too, but I wanted to intercept it to add some py code [070305]:
            ## Set( stateref.value, not_Expr(var) ),
            sbar_text=use_sbar_text))
    # note: using DisplayListChunk in _value works & is faster [070103]
    #070124 comment: the order DisplayListChunk( Highlightable( )) presumably means that the selobj
    # (which draws the highlightable's delegate) doesn't include the displist; doesn't matter much;
    # that CenterY(use_label) inside might be ok, or might be a bug which is made up for by the +0.5 I'm adding to drawfont2
    # in testdraw.py today -- not sure.
    incr_drawable = Instance(
        Boxed(CenterY(checkbox), pixelgap=0, bordercolor=gray, borderwidth=2))

    # I tried orange as a warning color -- means the checkbox reflects an intention but not yet the reality.
    # But it was annoyingly too visible. So I'll try gray.
    # If all colorboxeds are unpopular, then try an image that has a little spray of lines coming from the center, instead.
    def on_press(self):
        self.stateref.value = not self.stateref.value  # was, in the expr: Set( stateref.value, not_Expr(var) )

        ###e revise this code to use self.draw_incrementally once that's refiled into Highlightable ###e
        def func(self=self):
            self.incr_drawable.draw()
            ## self.draw() # includes the label - probably a waste but who cares
            self.env.glpane.swapBuffers()  # update display [needed]

        ran_already_flag, funcres = self.run_OpenGL_in_local_coords(
            func)  # this method runs in the Highlightable made in _value
        assert ran_already_flag
        return

    pass  # end of class checkbox_pref
示例#2
0
class SimpleColumn(Widget2D): #061115
    #e or use InstanceMacro using Overlay & Translate? Could work, but slower and not needed... might help in CL with fancier gaps.
    ## a0 = Arg(Widget2D) # note: this probably doesn't preclude caller from passing None, and even if it does, nothing enforces that yet;
        # if caller does pass None (to this or to Overlay), best thing is probably to replace this with Pass = Rect(0,0,white)
        # and use it as a drawable, but have special case to use no gap under it -- or the equiv, as a simple change
        # to our btop formula so it's 0 if not a0 -- which is already done, so maybe there's no need to worry about a0 = None.
        # Maybe it should be an optional arg like the others. [061115]
    a0 = Arg(Widget2D, None) # even the first arg can be missing, as when applying it to a list of no elts [061205]
    a1 = Arg(Widget2D, None)
    a2 = Arg(Widget2D, None)
    a3 = Arg(Widget2D, None)
    a4 = Arg(Widget2D, None)
    a5 = Arg(Widget2D, None) # use ArgList here when that works
    a6 = Arg(Widget2D, None)
    a7 = Arg(Widget2D, None)
    a8 = Arg(Widget2D, None)
    a9 = Arg(Widget2D, None)
    a10 = Arg(Widget2D, None)
    a11 = Arg(Widget2D, None) # the 12th arg is 1 too many
    toomany = Instance(TextRect("too many args to SimpleColumn"))
        #070212 added Instance to fix mysterious bug manifesting as this debug output:
        ## getattr_debugprint: <lexenv_ipath_Expr... <TextRect#2331(a)>> has no 'bleft'
    args = list_Expr(a0,a1,a2,a3,a4,a5, a6,a7,a8,a9,a10, # could say or_Expr(a0, Spacer(0)) but here is not where it matters
                     and_Expr(a11, toomany)
                     )
    
    ## gap = Option(Width, 3 * PIXELS)
    pixelgap = Option(float, 3) # 070104 int -> float
    gap = pixelgap * PIXELS

    print_lbox = Option(bool, False) #061127 for debugging; should be harmless; never tested (target bug got diagnosed in another way)
    
    drawables = call_Expr(lambda args: filter(None, args) , args)
    ## empty = not drawables ###e BUG: needs more Expr support, I bet; as it is, likely to silently be a constant False; not used internally
    empty = not_Expr(drawables)
    bleft = call_Expr(lambda drawables: max([arg.bleft for arg in drawables] + [0]) , drawables)
        # 070211 arg.bleft -> getattr_debugprint(arg, 'bleft')
    bright = call_Expr(lambda drawables: max([arg.bright for arg in drawables] + [0]) , drawables)
    height = call_Expr(lambda drawables, gap: sum([arg.height for arg in drawables]) + gap * max(len(drawables)-1,0) , drawables, gap)
    ## btop = a0 and a0.btop or 0  # bugfix -- use _Expr forms instead; i think this form silently turned into a0.btop [061205]
    btop = or_Expr( and_Expr( a0, a0.btop), 0)
    bbottom = height - btop
    def draw(self):
        if self.print_lbox:
            print "print_lbox: %r lbox attrs are %r" % (self, (self.bleft, self.bright, self.bbottom, self.btop))
        glPushMatrix()
        prior = None
        for a in self.drawables:
            if prior:
                # move from prior to a
                dy = prior.bbottom + self.gap + a.btop
                glTranslatef(0,-dy,0) # positive is up, but Column progresses down
            prior = a
            self.drawkid(a) ## a.draw()
        glPopMatrix()
        return
    pass # end of class SimpleColumn or SimpleColumn_OLD
示例#3
0
class Overlay(InstanceOrExpr, DelegatingMixin):
    "Overlay has the size of its first arg, but draws all its args in the same place, with the same origin."
    # Note: we can't inherit from Widget2D, or we'd fail to delegate
    # e.g. bright to self.delegate, and pick up the default value instead!
    # I'm not yet sure whether the proper fix is to handle those defaults in some other way
    # (e.g. as a last-resort delegate of some sort -- maybe we could say right here (to a fancier
    #  version of DelegatingMixin), if you don't find the attr in self.delegate, look in Widget2D).
    # See also comments in InstanceMacro, about the same issue for it.
    # [061210 grabbing SimpleColumn's scheme for permitting up to 10 args, though ArgList is nim]
    a0 = Arg(
        Widget2D, None
    )  # so it's not a bug to call it with no args, as when applying it to a list of no elts [061205]
    a1 = Arg(Widget2D, None)
    a2 = Arg(Widget2D, None)
    a3 = Arg(Widget2D, None)
    a4 = Arg(Widget2D, None)
    a5 = Arg(Widget2D, None)
    a6 = Arg(Widget2D, None)
    a7 = Arg(Widget2D, None)
    a8 = Arg(Widget2D, None)
    a9 = Arg(Widget2D, None)
    a10 = Arg(Widget2D, None)
    a11 = Arg(Widget2D, None)
    args = list_Expr(
        a0,
        a1,
        a2,
        a3,
        a4,
        a5,
        a6,
        a7,
        a8,
        a9,
        a10,  # could say or_Expr(a0, Spacer(0)) but here is not where it matters
        and_Expr(a11, TextRect("too many args in Overlay")))

    delegate = or_Expr(a0, Spacer(0))  ## _self.a0 # needed by DelegatingMixin

    ##    args = list_Expr(arg0, arg1) # not sure if [arg0, arg1] would work, but I doubt it --
    ###e should make it work sometime, if possible (e.g. by delving inside all literal list ns-values in ExprsMeta)
    #e add an option to make each element slightly closer, maybe just as a depth increment? makes hover highlighting more complicated...
    def draw(self):
        args = self.args  # this order is correct since we set glDepthFunc to GL_LEQUAL (not GL_LESS)
        for a in args:
            self.drawkid(a)
            #e We'd like this to work properly for little filled polys drawn over big ones.
            # We might need something like z translation or depth offset or "decal mode"(??).
            # [later 070404: "decal mode" is probably unrelated -- GL_DECAL is for combining a texture with a non-textured color/alpha,
            #  not related to using depth buffer when resulting textured object is drawn. Is "decal" used to mean anything else?? #k]
            # Different depth test would be best [done now -- GL_LEQUAL], but roundoff error might make it wrong...
            # This is definitely needed for overdrawing like that to work, but it's low priority for now.
            # Callers can kluge it using Closer, though that's imperfect in perspective mode (or when viewpoint is rotated).
            # [Or glDepthRange, now used for highlight drawing in GLPane as of 070921.]

    pass  # Overlay
示例#4
0
class SimpleRow(Widget2D):
    # copy of SimpleColumn, but bbottom <-> bright, btop <-> bleft, width <- height, and 0,-dy -> dx,0, basically
    a0 = Arg(Widget2D, None)
    a1 = Arg(Widget2D, None)
    a2 = Arg(Widget2D, None)
    a3 = Arg(Widget2D, None)
    a4 = Arg(Widget2D, None)
    a5 = Arg(Widget2D, None)  # use ArgList here when that works
    a6 = Arg(Widget2D, None)
    a7 = Arg(Widget2D, None)
    a8 = Arg(Widget2D, None)
    a9 = Arg(Widget2D, None)
    a10 = Arg(Widget2D, None)
    a11 = Arg(Widget2D, None)
    toomany = Instance(TextRect("too many args to SimpleRow"))
    args = list_Expr(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
                     and_Expr(a11, toomany))

    pixelgap = Option(int, 3)
    gap = pixelgap * PIXELS

    drawables = call_Expr(lambda args: filter(None, args), args)
    empty = not_Expr(drawables)
    btop = call_Expr(
        lambda drawables: max([arg.btop for arg in drawables] + [0]),
        drawables)
    bbottom = call_Expr(
        lambda drawables: max([arg.bbottom for arg in drawables] + [0]),
        drawables)
    width = call_Expr(
        lambda drawables, gap: sum([arg.width for arg in drawables]) + gap *
        max(len(drawables) - 1, 0), drawables, gap)
    bleft = or_Expr(and_Expr(a0, a0.bleft), 0)
    bright = width - bleft

    def draw(self):
        glPushMatrix()
        prior = None
        for a in self.drawables:
            if prior:
                # move from prior to a
                dx = prior.bright + self.gap + a.bleft
                glTranslatef(dx, 0,
                             0)  # positive is right, and Row progresses right
            prior = a
            self.drawkid(a)  ## a.draw()
        glPopMatrix()
        return

    pass  # end of class SimpleRow
示例#5
0
class SimpleColumn_NEW(Widget2D): #061115, revised 070321 to use new ArgList -- but disabled 070322,
    # since too slow for routine use (eg in testexpr_19g),
    # until we fix that update speed bug which means a change in any element remakes them all.
    ### fyi: a test that puts too many elts for SimpleColumn_OLD into the MT: _30i, dna x 3, rects x 2

    #e or use InstanceMacro using Overlay & Translate? Could work, but slower and not needed... might help in CL with fancier gaps.
    ## a0 = Arg(Widget2D) # note: this probably doesn't preclude caller from passing None, and even if it does, nothing enforces that yet;
        # if caller does pass None (to this or to Overlay), best thing is probably to replace this with Pass = Rect(0,0,white)
        # and use it as a drawable, but have special case to use no gap under it -- or the equiv, as a simple change
        # to our btop formula so it's 0 if not a0 -- which is already done, so maybe there's no need to worry about a0 = None.
        # Maybe it should be an optional arg like the others. [061115]
    args = ArgList(Widget2D, (), doc = "0 or more things (that can participate in 2d layout) to show in a column")
    def _C_a0(self):
        args = self.args
        args[0:] # make sure this works (i.e. args is a sequence)
        if len(args):
            return args[0]
        else:
            return None
        pass
    a0 = _self.a0 # kluge, but legal (due to special case in ExprsMeta, documented in comments there):
        # get a0 into the class-def namespace for direct use below

    def _init_instance(self):##### debug only
        super(SimpleColumn, self)._init_instance()
        try:
            args = 'bug' # for use in error message, in case of exception
            args = self.args
            len(args) # make sure this works!
            if debug070321:
                print "fyi: this SimpleColumn has %d args" % len(args)
                print "fyi: the args i mentioned are: %r" % (args,) #####
        except:
            print "following exception concerns self = %r, args = %r" % (self, args)
            raise
        return
    
    ## gap = Option(Width, 3 * PIXELS)
    pixelgap = Option(float, 3) # 070104 int -> float
    gap = pixelgap * PIXELS

    print_lbox = Option(bool, False) #061127 for debugging; should be harmless; never tested (target bug got diagnosed in another way)
    
    drawables = call_Expr(lambda args: filter(None, args) , args)
    ## empty = not drawables ###e BUG: needs more Expr support, I bet; as it is, likely to silently be a constant False; not used internally
    empty = not_Expr(drawables)
    bleft = call_Expr(lambda drawables: max([arg.bleft for arg in drawables] + [0]) , drawables)
        # 070211 arg.bleft -> getattr_debugprint(arg, 'bleft')
    bright = call_Expr(lambda drawables: max([arg.bright for arg in drawables] + [0]) , drawables)
    height = call_Expr(lambda drawables, gap: sum([arg.height for arg in drawables]) + gap * max(len(drawables)-1,0) , drawables, gap)
    ## btop = a0 and a0.btop or 0  # bugfix -- use _Expr forms instead; i think this form silently turned into a0.btop [061205]
    btop = or_Expr( and_Expr( a0, a0.btop), 0)
    bbottom = height - btop
    def draw(self):
        if self.print_lbox:
            print "print_lbox: %r lbox attrs are %r" % (self, (self.bleft, self.bright, self.bbottom, self.btop))
        glPushMatrix()
        prior = None
        for a in self.drawables:
            if prior:
                # move from prior to a
                dy = prior.bbottom + self.gap + a.btop
                glTranslatef(0,-dy,0) # positive is up, but Column progresses down
            prior = a
            self.drawkid(a) ## a.draw()
        glPopMatrix()
        return
    pass # end of class SimpleColumn_NEW or SimpleColumn
示例#6
0
class PalletteWell(DelegatingInstanceOrExpr):
    """A place in the UI which can make copies of its expr for dragging to whereever you want [not fully working yet]
    """
    # experimental, really a stub, 070212 -- but sort of works! (as tested in dna_ribbon_view.py)
    expr = ArgExpr(
        Anything
    )  #e not really Anything, but some interface ##e should really be StateArg

    world = Option(
        World
    )  ###e find in env, instead?? maybe not, since in typical cases we might rather make in some parent in
    # the model anyway, which depends on which kind of obj we are and which pallette we're in...
    # maybe we even need a make-function to be passed in.
    # If it was an arg, it'd be natural as arg1 (since this is like a method on the world);
    # but since it might become a dynamic env var, I'll use an option for now.
    # If it was a dynamic var by default but could be some container obj, an option would be good for that too (renamed #e).

    type = Option(
        str,
        doc=
        "type of thing to tell world we're making [type, api subject to change]"
    )
    ###BUG: passing type to world.make_and_add is nim
    what_to_make_nickname = or_Expr(
        type, "something"
    )  #e classname of expr, after burrowing? some other namelike attr of expr?
    # (note, hard to have that, unless expr is a new special Instance type of "makable" rather than a bare expr --
    #  and it probably ought to be. ##e)

    sbar_text = Option(str, format_Expr("make %s", what_to_make_nickname))

    _what_to_make = DraggableObject(_self.expr)
    ##e rename DraggableObject -> Draggable? I misrecalled it as that... and "object" is arguably redundant.

    _newobj = State(
        Anything,
        None)  # set internally to an object we create during _self.on_press

    delegate = Highlightable(
        Boxed(expr, borderthickness=2 * PIXELS),  # plain
        ###BUG: Boxed fails with exprs that don't have bleft, with a very hard to decipher exception
        Boxed(expr, borderthickness=2 * PIXELS, bordercolor=blue),  # highlight
        Boxed(expr, borderthickness=2 * PIXELS, bordercolor=green
              ),  # [pressed] green signifies "going" (mainly, green != blue)
        on_press=_self.on_press,
        on_drag=_newobj.on_drag,
        on_release=_newobj.on_release,
        sbar_text=
        sbar_text  ###e UI DESIGN: need to also pass sbar text (or a func to get it from selobj) for use during the drag
    )

    def on_press(self):
        # make a new object
        self._newobj = self.world.make_and_add(self._what_to_make)
        ##e also pass the type option, taken from a new _self option?
        ###e UI DESIGN FLAW: we should probably not actually make the object until the drag starts...
        # better, make something now, but only a fake, cursor-like object (not placed in the model or its tree)
        # (maybe a thumbnail image made from expr? maybe use PixelGrabber on self, to get it?? #e)
        # and only make a real model object when the drag *ends* (in a suitable mouse position -- otherwise cancel the make).

        if 'kluge 070328, revised 070401':  ###e see also comments in class World, 070401
            self._newobj.copy_saved_coordsys_from(self.world._coordsys_holder)
        # start a drag of the new object; first figure out where, in world coordinates, and in the depth plane
        # in which you want the new object to appear (and move the object there -- without that it'll be at the origin)
        point_in_newobj_coords = self._newobj.current_event_mousepoint(
            plane=ORIGIN)
        ### LOGIC BUG: this seems to work, but it presumbly has this bug: in current implem, self._newobj's local coordsys
        # can't be available yet, since it's never been drawn! So it presumably gives out a debug message I've been seeing
        # ("saved modelview_matrix is None, not using it")
        # and uses global modelview coords, which happen to be the same in the current test (in dna_ribbon_view.py).
        ###KLUGE: use ORIGIN (which we know) in place of center of view (which we don't) -- only correct when no trackballing
        self._newobj.motion = point_in_newobj_coords
        ###KLUGE since it centers new obj on mouse, even if mousedown was not centered on sample obj
        ###BUG (confirmed): I bet the point would be wrong in perspective view, unless we first corrected the depth plane,
        # then reasked for point.
        # trying that 070217 -- But how to fix? To correct the plane, we need to flush the DraggableObject in self._newobj, at least,
        # before current_event_mousepoint is likely to use correct coords (actually I'm not sure -- ###TEST)
        # but we can't since not all objects define .move (need to ###FIX sometime).
        ## self._newobj.flush()
        # so try this even though it might not work:
        ##        point_in_newobj_coords_2 = self._newobj.current_event_mousepoint(plane = ORIGIN)
        ### but now, what do we do with this point???
        # print "debug note: compare these points:",point_in_newobj_coords, point_in_newobj_coords_2 # result: identical coords.
        # so it doesn't work and doesn't even make sense yet... i probably can't proceed until the logic bug above is fixed.
        # There's also the issue of different object size on-screen if it's shown at a different depth.
        # (Unless that could help us somehow, in showing the depth? doubtful.)
        ### UI DESIGN FLAWS: the new obj is obscured, and there is no visual indication you "grabbed it", tho you did.
        # (actually there is one, if you wait long enough and didn't happen to grab it right on the center! but it's subtle --
        #  and worse, it's arguably due to a bug.)
        ##e would box border color change help? or box "dissolve"?? (ie temporarily remove the box)
        # or we might need to hide the pallette well (or make it translucent or not depth-writing)
        ###e need sbar messages, some message that you grabbed it (which would mitigate the visual flaw above)
        self._newobj.on_press(
        )  # needed so its on_drag and on_release behave properly when we delegate to them above
        return

    pass  # end of class PalletteWell