def on_press_bg(self): if 0: print "compare:" print self, self.delegate, self.delegate.delegate, self.delegate.delegate.plain # the background print self.background print "hl.highlighted =",self.delegate.delegate.highlighted # self.background is the same as the .plain printed above, which means, as of 061208 941pm anyway, # instantiating an instance gives exactly that instance. (Reasonable for now...) point = self.current_event_mousepoint() #e note: current_event_mousepoint is defined only on Highlightable, for now (see comments there for how we need to fix that), # but works here because we delegate ultimately to a Highlightable, without changing local coords as we do. # note: lots of devel scratch & debug comments removed 061207; see cvs rev 1.5 for them. # for initial test, don't use those Command classes above, just do a side effect right here ###kluge newpos = point + DZ * DZFUZZ # kluge: move it slightly closer so we can see it in spite of bg ###e needs more principled fix -- not yet sure what that should be -- is it to *draw* closer? (in a perp dir from surface) #e or just to create spheres (or anything else with thickness in Z) instead? (that should not always be required) ###BUG: DZ is not always the right direction! [more comment on that in demo_draw_on_surface.py] if not self.use_VertexView: # old code ## print "make node in old way (not using VertexView)" # still running as of 070115 at least in testexpr_19f node_expr = Vertex(newpos, Center(Rect(0.2,0.2, ## 'green', -- now we cycle through several colors: (colors,...)[counter % 6] ## tuple_Expr(green,yellow,red,blue,white,black)[mod_Expr(_this(Vertex).ipath[0],6)] red # the above worked ok until tested 070121 morn -- ipath now starts with string. # it was a kluge anyway, so disable it until we can rework it to be sensible. ))) else: # new code, being written 070105, just getting started -- mostly nim node_expr = Vertex_new(newpos, # cycle through several colors: (colors,...)[counter % 6] color = tuple_Expr(green,yellow,red,blue,white,black)[mod_Expr(_this(Vertex).ipath[0],6)] ) pass ## draggable_node_expr = Highlightable(node_expr, on_drag = _self.on_drag_node, sbar_text = "dne") ###BUG: this breaks dragging of the new node; it fails to print the call message from on_drag_node; # if you try to drag an old node made this way, it doesn't work but says # debug fyi: len(names) == 2 (names = (268L, 269L)) # Guess: limitation in current rendering code makes it not work for any nested glnames, but just print this instead... # (note: even after reload, the node objects in the world have their old Vertex class, and the old expr used to make them) # # [later 061213:] IIRC the status was: I made GLPane_overrider so I could fix that 2-glname issue in it, # but never got to that yet. Meanwhile I commented out the use of this expr, and thus on_drag_node is never used... # and Vertexes dragged directly do nothing -- they're highlightable but with no actions. # And World could probably draw them highlightable even if they weren't, but it doesn't. # BTW the disabled nonworking draggable_node_expr is not well-designed -- it does not add a Vertex to World, it adds a # draggable one -- but even World is not perfect, since it contains Vertexes (not just their data) # and they inherently have (a lack of) action bindings since they are Highlightable. # Probably better would be if World contained data-nodes and had access to (or had its own) display rules for them # which added commands/actions based on the currently active tools. That would help with tool-code-reloading too. # Probably some other comments here say this too. # # So does a World need a formula or function arg for how to map its data objects to display objects, at the moment? # Or is there some scheme of a global map for that, to be applied when "drawing" any data object? # And do some data objs have their own positions, or is that always supplied by the world or other data obj they're in? # In theory, we might display atoms at posns unrelated to atom.pos, e.g. as a row in a table which includes their coords. # So it's more like we have ways of "drawing a set of things" which can say "at posns given by func(thing)" # or "at successive posns in a column", corresponding to two display forms with different exprs, # with the map from thing to individual display form also needing to be specified. # So a World is more like a set of things, and it can have a display mode (or more than one), given a thing-display-function. # We can ask it or anything else how it recommends displaying itself given display style options, # but we can choose to use that display function (from it to a more directly displayable object) or use another one. # Or we can probably just "draw it" and have it pick up the current display style from the env (including the # currently active tools). Is there any reason not to permit both? (draw using current style, draw using given style, # give me function from you to drawables using given style, use specific function and draw the results -- all possible.) # # If a thing in a world has standard mouse actions of its own, can it also have "grabbable areas" for use in dragging it # when it has a posn as displayed in some world? Or did that world have to explicitly turn it into a draggable thing? # Answer: both. The world turns it into that by adding a drag binding for those "overall handles" the thing has. # It might draw them with glnames in some set it knows... ie as named subobjs of itself. The overall thing might also # have a single name. Then we have a sequence of two glnames meaning obj/subobj which we want to use to determine the action. # For some subobjs that's within the object and supplied by it (perhaps depending on tool); for others, # it's supplied by the World it's in (also dep on a tool) and handled by it (eg move the obj, select the obj). # # For the simple things we have there, there are no subobjects, and no actions except drag or later select the whole thing. # A simple model is "one thing was hit, but some things are specified by a specific series of two or more glnames". # In general the outer name decides how to interpret (or whether to ignore) the inner names. # It can map the inner ones somehow... not sure how. This will relate a lot to DisplayListChunk when we have that. # Mere nested Highlightables might push two names but both would be unique. Outer name might just defer to inner one then. if 0: ## MAKE THIS WORK: draggable_node_expr = 'define this' newnode = self.world.make_and_add( draggable_node_expr, type = "Vertex") else: newnode = self.world.make_and_add( node_expr, type = "Vertex") #070206 added type = "Vertex" self.newnode = newnode ###KLUGE that we store it directly in self; might work tho; we store it only for use by on_drag_bg return # from on_press_bg
class ToggleShow(InstanceMacro): # args thing = Arg(Widget2D) label = Arg(Widget2D, TextRect("label")) #e or coerce text into a 1-line TextRect -- how do we declare that intent?? if 0: # first make it work with a self-made stateref only, imitating Highlightable, using transient state stateref = Arg(StateRef, Automatic) ###k assumes the dflt can be a way to make one, not a literal one ## Q: how does each stateref we have, e.g. the one here meant for 'open', relate to StatePlace args # we might make or get from a superclass? (like the ones now in Highlightable.py but to be moved to a super of it) # if caller passes one, no need for our own, but to make our own, we'd make it in a StatePlace of our own, I think. ##e 061117 if 0 and 'maybe': ##e might need to also say it's supposed to be boolean # note, on 070115 I revised StateRef (still a stub) but might have broken it due to the arg being passed here (not tested) stateref = Arg(StateRef(bool), Automatic) ##e and also spell out the default location -- assume ipath itself can be coerced into the full stateref stateref = Arg(StateRef(bool), _self.ipath) ####k is ipath local to something like _self, or only rel to the entire model?? his matters if we name the statepath here! stateref = Arg(StateRef(bool), _my_node.open) ###k assumes _my_node.open can be an lval even after _my_node is bound! ####k ##e or we could spell out the default stateref as _self.ipath, assuming that can be coerced into one -- # of course it can't, we also need to say it's boolean (openQ: open is true, closed is false) and with what encoding. # but come to think of it, that is not part of the arg, right? the arg is "some boolean state"... hmm, i guess it is. # but the arg can also be "where to store the state, of whatever kind you want". And we say the type and encoding # if the arg doesn't -- as if the caller can supply partial info in the arg, and we supply defaults rather than # making them get made up by the bare argtype -- which could work by just using a fancified argtype created here. # which the Arg macro could make for us somehow... but that can all wait for later. For now, # we can detect the boolean type by how we try to use the arg, i guess... not sure, maybe just say it right here. # and the default encoding for bools (known to the bool type, not custom to us) is fine. if 1: # works fine, but as of 061126 late, comment out the remaining stmt, since done in InstanceOrExpr superclass rather than here pass ## transient_state = StatePlace('transient') #e move into super along with the ones in Highlightable of which this is a copy #e rename stateref to be specific for open, maybe open_stateref, in that if 0 code above # devel scratch: transient_state is an attr_accessor, which lets you do getattr and setattr. # but what we want it to do for us is tell us an lval for the attr 'open' # so we can retain that, attached to self.open somehow -- as its actual lval, maybe? not sure. # but much like that, since get or set self.open should work that way. # so a stateref (instance of StateRef) is basically an instance which acts as an lval... and can be attached to an attr. # But ExprsMeta right now insists on making its own lval, being passed a formula. Should we kluge-adapt to that or change it? # Guess: better & maybe easier to change it. So we have a new kind of object, not a formula (or a special kind of one), # to use as an rhs and process by ExprsMeta. It's not an lval, that's per-Instance. Is it a formula for making an lval?### # But it might be semantically different, since we don't store the lval as the value for self.open, # but as the value for its lval. hmm.... can we tell ExprsMeta to do this by an assignment to open # of a wrapped formula? it means, get the lval not by making one whose vals come from this formula # but make a property whose lvals come from this formula (which should be per-instance but time-constant, maybe, # tho if not time constant, it might be ok -- not sure ##e). ## open = State('transient','open') ### hmm... maybe 'open' needn't be passed if it gets it like Arg or Option does... maybe the kind is also default something? # so: open = State()? bt say the type and dfault val -- like I did in this: # staterefs.py: 181: LocalState( lambda x = State(int, 1): body(x.value, x.value = 1) ) # # see if this gets the expected asfail: it does! [061121 late] ## set_default_attrs( transient_state, open = True) if 0: # this will be real code someday when no longer nim, but use an easier way first. open = State(bool, True) # default 'kind' of state depends on which layer this object is in, or something else about its class # but for now make it always transient_state # this is a macro like Option # it takes exprs for type & initial val # but those are only evalled in _init_instance or so -- not yet well defined what happens if they time-vary # and note, that form doesn't yet let you point the state into a storage place other than _self.ipath... should it?? # but the importance is, now in python you use self.open for get and set, just as you'd expect for an instance var. else: def get_open(self): #k return self.transient_state.open def set_open(self, val): #k self.transient_state.open = val return open = property(get_open, set_open) pass def _init_instance(self): super(ToggleShow, self)._init_instance() set_default_attrs( self.transient_state, open = True) # constants # Note, + means openable (ie closed), - means closable (ie open) -- this is the Windows convention (I guess; not sure about Linux) # and until now I had them reversed. This is defined in two files and in more than one place in one of them. [bruce 070123] open_icon = Overlay(Rect(0.4), TextRect('-',1,1)) closed_icon = Overlay(Rect(0.4), TextRect('+',1,1)) if 0: open_icon = TextRect('-',1,1) #stub closed_icon = TextRect('+',1,1) #stub else: ####@@@@ I vaguely recall that Highlightable didn't work on text! # and indeed, highlighting doesn't seem to be working on those. # if so, the above'll need revision until that's fixed. # BUT, with these grays anyway, clicks on the text are working. But it might be because the grays are behind them. ###k if 0 and 'varying rect sizes': # how it was during debugging open_icon = Overlay(Rect(0.5,1), TextRect('-',1,1)) # added 0.5 061120 1018p temp debug kluge closed_icon = Overlay(Rect(1,0.5), TextRect('+',1,1)) #061120 changed impicit 1 -> 0.5 else: # easier on the mouse-hand and eye open_icon = Overlay(Rect(0.4), TextRect('-',1,1)) # added 0.5 061120 1018p temp debug kluge closed_icon = Overlay(Rect(0.4), TextRect('+',1,1)) #061120 changed impicit 1 -> 0.5 # _value, and helper formulae ## open = stateref.value # can we make it work to say Set(open, newval) after this?? ####k # the hard part would be: eval arg1, but not quite all the way. we'd need a special eval mode for lvals. # it'd be related to the one for simplify, but different, since for (most) subexprs it'd go all the way. ## openclose = If( open, open_icon, closed_icon ) # Status as of 061121 421p: both if 0 and if 1 cases seem to work fine, provided you restart when changing between them. # (Testing was not extensive, so it might turn out that avoiding other reloads is also needed.) # The known bugfixes that led to this: # - selobj = None in some places (not sure which are needed). # - no usage/change tracking by stateplaces that get set during draw (or that contain glname -- don't know if that matters). # - no usage/change tracking by set_default_attrs. # And other changes that might be helping: # - don't recycle glnames. # - some others I forget, which are marked by 061120 (or maybe 061121) # in comments or stringlits (in this or other files). # - don't track_use on exception in Lval get_value (BUT, i suspect it's actually wrong not to; see cmt there 061121) # - more conservative selobj_still_ok # - mode.update_selobj(event) in leftClick and ReleasedOn # - self.inval(mode) #k needed? (done in two places per method, guess is neither is needed) # # Soon, the needed or not of the above workarounds should be sorted out, # and most of the following debugging-log commentary should be removed. #e if 1: openclose = Highlightable( If_kluge( open, open_icon, closed_icon ), on_press = _self.toggle_open, sbar_text = _this(Highlightable).ipath # this line just for debugging ) ##e we should optim Highlightable's gl_update eagerness # for when some of its states look the same as others! # (no gl_update needed then, at least not just for that change -- # note, this is a special case of the inval optim for when something was changed to an equal value) #e someday be able to say: # on_press = Set( open, not_Expr(open) ) ## silly: on_press = lambda open = open: open = not open # no, open = not open can't work # in fact, you can't use "lambda open = open", since open has to be replaced by ExprsMeta ##k can on_press be an expr to eval, instead of a (constant expr for a) func to call?? ####k ## on_press = call_Expr( lambda xxx: self.open = not self.open, xxx) # no, no assignment in lambda pass else: # so try this form 155p - bug of not working is gone, but now, it always draws the + form! Is it drawing the old one # due to same glname? no (I guess), they should have different names! # is it drawing old one due to not realizing that one is obs? ######where i am # is it failing to invalidate the drawing effect of this instance? (after all, who is it that sees the usage of open? # it must be glpane as if we were using a prefs variable here! is that sufficient?? does it work ok re selobj system???###) # IS THE CHOICE OF DELEGATE being invalled? I think so, since I see the alignment calcs get updated, # or is that just the live gltranslate inside the draw method? # HEY, when I covered up the glpane with this app, then uncovered it, suddenly I see the new selobj, # then the conjunction of both! how can that be? thes are similar to whgat I sawe earlier. conclusion: weird update bugs # in selobj/highlight system, i guess. (maybe it does the main draw and highlight draw on different objects? # try altering color, or using 4 images not 2. ###) # now it sems that mouse around on the closed that looks like open is what makes it look like clsed, or like both. # yes, repeatable, for either change of state. Ok, try that in 'if 1' case of this. ### siilar but not identical # and that time is again does get stuck into the closed state, with the grayrect no longer optiming redraws re stencil buffer. # .. reviewing code in Highlightable, I see some things to try -- see its 061120 comments. # ... I did all that, and the 'gray becomes inactive bug' in 'if 1 openclose case' is still there. howbout the if 0 case? # [later: i think that still had some bad bugs too, not much changed.] # for more, see string lits containing 061120, and for a log see big cmt just below here. openclose = If_kluge( open, ## Highlightable(open_icon, on_press = _self.toggle_open, sbar_text = _self.ipath), ## Highlightable(closed_icon, on_press = _self.toggle_open, sbar_text = _self.ipath), ###BUG - same ipaths? NO, I USED _self BUT MEANT _this(Highlightable)!!! AAArgh! ##k works now?? yes Highlightable(open_icon, on_press = _self.toggle_open, sbar_text = _this(Highlightable).ipath), Highlightable(closed_icon, on_press = _self.toggle_open, sbar_text = _this(Highlightable).ipath), ) pass def toggle_open(self): if 'yet another shot in the dark 061120 1001p': self.env.glpane.selobj = None ##### THIS SEEMS TO FIX THE BUG, at least together with other potshots and if 0 openclose. # theory: old selobjs are being drawn highlighted even when not drawn normally. they mask the real stuff. # but with if 1 openclose it doesn't fix the different bug (gets wedged into closed state). why not??? # this is with no recycling of names, and also selobj=None in recycler. # guess: in if 1, the same glname is used... but it's same literal selobj too, right? and remaking is turned off. # I don't have a theory for 'if 1' bug cause, or for why it only affects the inner thing, not outer one. # Does it only affect that after it's once been hidden? ### if so, is it "you were selobj and then not drawn" that makes it # happen? that might fit the data but I don't see how that could work. # So I added a 2nd 0.5 so neither gray rect form covers the other. but first inner close hits the bug of making it # inactive and act non-highlighted. so i wondered if the glname really only covers the openclose? code says so. # I added a try/except to be sure the PopName occurs; not triggered during this if 1 bug. # # Stopping for night 061120 1027p, summary: I understand some bug causes but not all; wish I could see inside the glselect # reasoning, so plan to add debug prints to glpane. Need to think thru its assumptions re chaotic glname/selobj/size/ # whether-drawn situation, see which are wrong, which might cause the bug. Also - can event processing occur during # paintGL? I hope not, but verify. Also maybe GLPane needs to track frame numbers for selobjs being drawn, # stencil bits being made, vs selobj state mods as tracked by inval.... # # update 061121 953a, where I am: after basic fixes elsewhere [some stateplaces not tracked, some usage tracking disallowed], # and still using all kluge/workarounds from 061120, bug seems totally fixed for if 0 case, all or most for if 1 ##k. # IIRC it was slightly remaining before some usage tracking disallowed, but that is not complaining, which is suspicious. # Anyway, if if 1 works too, plan is to gradually remove the kluges and clean up and keep it working. # BUT it looks like if 1 (using reloaded code) has a bug of some disallowed usage... details to follow. # BUT after restart I don't see it. BTW I recently reenabled reloading -- could that have fixed some bugs (how???), # or could it be that they now occur after reloading but not before it?? indeed, this is after changing if 1->0 and reload, # and looks like it might relate to old state being there, and ###### WHAT IF RELOADED CODE USES THE SAME STATE DIFFERENTLY AND HAS A BUG? ##### # [but, that bug aside, there is still a real problem with whatever usage tracking this # set_default_attrs is doing. [fixed now]] if 0: #061121 822p i've been using if 1 forever, let's see if if 0 works here: it does! either is ok, given the open property. old = self.transient_state.open self.transient_state.open = new = not old ## print "toggle_open changed self.transient_state.open from %r to %r" % (old, new,) else: old = self.open self.open = new = not old ## print "toggle_open changed self.open from %r to %r" % (old, new,) # [obs cmt re open property, but was it talking about that or a partly working State decl? as of 061121 I can't remember:] # should work but doesn't, see bug in notesfile, it delegates self.open eval to _value: 061118 late # (or is it just because the val was not initialized? GUESS, YES ###k) ## self.open = not self.open ### can this work??? it will call set of self.open -- what does the descriptor do for that? # (asfail, or not have __set__ at all?? FIND OUT. the notesfile says the same thing but for a different Q, what was it?) ## WE SHOULD MAKE THIS WORK even if we also make on_press = Set( open, not_Expr(open) ) work, since it's so natural. ### BTW what is it that will notice the inval, and the usage of this when we drew, and know that gl_update is needed? # the same thing that would know a display list content was invalid -- but where is it in our current code (if anywhere)? # I vaguely recall a discussion of that issue, in the displist chunk code or notesfile, weeks ago. # some way to have lvals representing displist contents or frame buffer contents, whose inval means an update is needed. printnim("toggle_open might do a setattr which is not legal yet, and (once that's fixed) might not properly gl_update yet") return _value = SimpleRow( openclose, SimpleColumn( label, If_kluge( open, thing, TextRect("<closed>") #####BUG: I wanted None here, but it exposes a logic bug, # not trivial to fix, discuss in If or Column [see also a discussion in demo_MT.py, 070302]; ##e Spacer(0) can also be tried here [##e should what to show here be an arg??] ) ) ) ## if 0: # if 0 for now, since this happens, as semiexpected: ## ## AssertionError: compute method asked for on non-Instance <SimpleRow#3566(a) at 0xe708cb0> ## ## ##e do we want to make the height always act as if it's open? I think not... but having a public open_height attr ## # (and another one for closed_height) might be useful for some callers (e.g. to draw a fixed-sized box that can hold either state). ## # Would the following defns work:? ## ## # (They might not work if SimpleRow(...).attr fails to create a getattr_Expr! I suspect it doesn't. ####k ) ## ## # [WARNING: too inefficient even if they work, due to extra instance of thing -- see comment for a fix] ## open_height = SimpleRow( ## open_icon, ## SimpleColumn( ## label, ## thing ## )).height ##k if this works, it must mean the SimpleRow gets instantiated, or (unlikely) ## # can report its height even without that. As of 061116 I think it *will* get instantiated from this defn, ## # but I was recently doubting whether it *should* (see recent discussions of TestIterator etc). ## # If it won't, I think wrapping it with Instance() should solve the problem (assuming height is deterministic). ## # If height is not deterministic, the soln is to make open_instance and closed_instance (sharing instances ## # of label), then display one of them, report height of both. (More efficient, too -- only one instance of thing.) ## # (Will the shared instance of label have an ipath taken from one of its uses, or something else? ## # Guess: from the code that creates it separately.) ## ## closed_height = SimpleRow( ## closed_icon, ## SimpleColumn( # this entire subexpr is probably equivalent to label, but using this form makes it more clearly correct ## label, ## None ## )).height pass # end of class ToggleShow
def on_press_bg(self): if 0: print "compare:" print self, self.delegate, self.delegate.delegate, self.delegate.delegate.plain # the background print self.background print "hl.highlighted =", self.delegate.delegate.highlighted # self.background is the same as the .plain printed above, which means, as of 061208 941pm anyway, # instantiating an instance gives exactly that instance. (Reasonable for now...) point = self.current_event_mousepoint() #e note: current_event_mousepoint is defined only on Highlightable, for now (see comments there for how we need to fix that), # but works here because we delegate ultimately to a Highlightable, without changing local coords as we do. # note: lots of devel scratch & debug comments removed 061207; see cvs rev 1.5 for them. # for initial test, don't use those Command classes above, just do a side effect right here ###kluge newpos = point + DZ * DZFUZZ # kluge: move it slightly closer so we can see it in spite of bg ###e needs more principled fix -- not yet sure what that should be -- is it to *draw* closer? (in a perp dir from surface) #e or just to create spheres (or anything else with thickness in Z) instead? (that should not always be required) ###BUG: DZ is not always the right direction! [more comment on that in demo_draw_on_surface.py] if not self.use_VertexView: # old code ## print "make node in old way (not using VertexView)" # still running as of 070115 at least in testexpr_19f node_expr = Vertex( newpos, Center( Rect( 0.2, 0.2, ## 'green', -- now we cycle through several colors: (colors,...)[counter % 6] ## tuple_Expr(green,yellow,red,blue,white,black)[mod_Expr(_this(Vertex).ipath[0],6)] red # the above worked ok until tested 070121 morn -- ipath now starts with string. # it was a kluge anyway, so disable it until we can rework it to be sensible. ))) else: # new code, being written 070105, just getting started -- mostly nim node_expr = Vertex_new( newpos, # cycle through several colors: (colors,...)[counter % 6] color=tuple_Expr(green, yellow, red, blue, white, black)[mod_Expr(_this(Vertex).ipath[0], 6)]) pass ## draggable_node_expr = Highlightable(node_expr, on_drag = _self.on_drag_node, sbar_text = "dne") ###BUG: this breaks dragging of the new node; it fails to print the call message from on_drag_node; # if you try to drag an old node made this way, it doesn't work but says # debug fyi: len(names) == 2 (names = (268L, 269L)) # Guess: limitation in current rendering code makes it not work for any nested glnames, but just print this instead... # (note: even after reload, the node objects in the world have their old Vertex class, and the old expr used to make them) # # [later 061213:] IIRC the status was: I made GLPane_overrider so I could fix that 2-glname issue in it, # but never got to that yet. Meanwhile I commented out the use of this expr, and thus on_drag_node is never used... # and Vertexes dragged directly do nothing -- they're highlightable but with no actions. # And World could probably draw them highlightable even if they weren't, but it doesn't. # BTW the disabled nonworking draggable_node_expr is not well-designed -- it does not add a Vertex to World, it adds a # draggable one -- but even World is not perfect, since it contains Vertexes (not just their data) # and they inherently have (a lack of) action bindings since they are Highlightable. # Probably better would be if World contained data-nodes and had access to (or had its own) display rules for them # which added commands/actions based on the currently active tools. That would help with tool-code-reloading too. # Probably some other comments here say this too. # # So does a World need a formula or function arg for how to map its data objects to display objects, at the moment? # Or is there some scheme of a global map for that, to be applied when "drawing" any data object? # And do some data objs have their own positions, or is that always supplied by the world or other data obj they're in? # In theory, we might display atoms at posns unrelated to atom.pos, e.g. as a row in a table which includes their coords. # So it's more like we have ways of "drawing a set of things" which can say "at posns given by func(thing)" # or "at successive posns in a column", corresponding to two display forms with different exprs, # with the map from thing to individual display form also needing to be specified. # So a World is more like a set of things, and it can have a display mode (or more than one), given a thing-display-function. # We can ask it or anything else how it recommends displaying itself given display style options, # but we can choose to use that display function (from it to a more directly displayable object) or use another one. # Or we can probably just "draw it" and have it pick up the current display style from the env (including the # currently active tools). Is there any reason not to permit both? (draw using current style, draw using given style, # give me function from you to drawables using given style, use specific function and draw the results -- all possible.) # # If a thing in a world has standard mouse actions of its own, can it also have "grabbable areas" for use in dragging it # when it has a posn as displayed in some world? Or did that world have to explicitly turn it into a draggable thing? # Answer: both. The world turns it into that by adding a drag binding for those "overall handles" the thing has. # It might draw them with glnames in some set it knows... ie as named subobjs of itself. The overall thing might also # have a single name. Then we have a sequence of two glnames meaning obj/subobj which we want to use to determine the action. # For some subobjs that's within the object and supplied by it (perhaps depending on tool); for others, # it's supplied by the World it's in (also dep on a tool) and handled by it (eg move the obj, select the obj). # # For the simple things we have there, there are no subobjects, and no actions except drag or later select the whole thing. # A simple model is "one thing was hit, but some things are specified by a specific series of two or more glnames". # In general the outer name decides how to interpret (or whether to ignore) the inner names. # It can map the inner ones somehow... not sure how. This will relate a lot to DisplayListChunk when we have that. # Mere nested Highlightables might push two names but both would be unique. Outer name might just defer to inner one then. if 0: ## MAKE THIS WORK: draggable_node_expr = 'define this' newnode = self.world.make_and_add(draggable_node_expr, type="Vertex") else: newnode = self.world.make_and_add( node_expr, type="Vertex") #070206 added type = "Vertex" self.newnode = newnode ###KLUGE that we store it directly in self; might work tho; we store it only for use by on_drag_bg return # from on_press_bg