class whatever(DelegatingInstanceOrExpr): ###e rename # simulates the env that demo_ui will provide (stub version, evolving to be more like it) ui_and_world = Instance(World()) ##### ###e following needs to permit cmd_DrawOnSurface to vary # (at least let it also be cmd_MakeRect; use a menu of options? or use one ActionButton per command, since more like a toolbar?) # -- but with Instance inside the variation, I think -- # ie it should be a map from the desired cmd expr to the cmd instance -- or, make a new one each time, so it's a cmdrun... # maybe see how demo_ui/toolbar was planning to do it... ###e toolbar = SimpleColumn( ActionButton( _self.do_cmd_DrawOnSurface, "button: cmd_DrawOnSurface" ), #e make the text from the command #e the running one should look pressed ActionButton(_self.do_cmd_MakeRect, "button: cmd_MakeRect"), ) ###e show it where? above PM for now? current_cmdrun = State( Anything, None ) # what is actually in here? an Instance of a "command run", [btw is None needed??] # or of a command obj that handles multiple runs (ie a command_runner?)... up to it to not get messed up if that happens # (and for now, unfortunately, not remaking it is probably a significant speed optim) # (so should we let an outer command handler have the PM and get reused, but an inner CommandRun get remade? why bother?) def do_cmd_DrawOnSurface( self ): #e which name is better: do_cmd or set_cmd? depends on type of command! self._do_cmd(cmd_DrawOnSurface) def do_cmd_MakeRect(self): self._do_cmd(cmd_MakeRect) def _do_cmd(self, cmd): "set self.current_cmdrun, etc..." # do we make a new one if button pressed when one already running?? yes for now. self.current_cmdrun = self.Instance( cmd(world=self.ui_and_world), id(cmd)) #e cache that expr? index ok? why cache instance? #old cmt: #e args? world? new object? does its super handle some? Command vs CommandRun? pm = current_cmdrun.property_manager corner_stuff = SimpleColumn(toolbar, pm) delegate = Overlay( current_cmdrun, DrawInCorner(corner_stuff, corner=PM_CORNER), ) def _init_instance(self): super(whatever, self)._init_instance() self.do_cmd_MakeRect( ) # or at least set some command, preferably a "null" or "default" one # note that this resets the current tool state on reload -- not really desirable; # how was demo_ui planning to handle that? ###k pass
def demo_drag_toolcorner_expr_maker(world): #070106 improving the above # given an instance of World, return an expr for the "toolcorner" for use along with GraphDrawDemo_FixedToolOnArg1 (on the same World) expr = SimpleColumn( checkbox_pref(kluge_dragtool_state_prefs_key, "drag new nodes?", dflt=kluge_dragtool_state_prefs_default), checkbox_pref(kluge_dragtool_state_prefs_key + "bla", "make polyline?", dflt=False), checkbox_pref(kluge_dragtool_state_prefs_key + "bla2", "(make it closed?)", dflt=False), ## ActionButton( world._cmd_Clear, "button: clear") # works # 070108: try this variant which uses _cmd_Clear_nontrivial: will the If work as an Expr?? If_kluge should tell us #####k ####k also will the type tests inside ActionButton work with an If? Probably not -- that's a ###BUG but I'll put it off. ## 1. make this work later: ActionButton( world._cmd_Clear, If_kluge( world._cmd_Clear_nontrivial, "button: clear", "button (disabled): clear")) ## 2. this too: If_kluge( world._cmd_Clear_nontrivial, ## ActionButton( world._cmd_Clear, "button: clear"), ## ActionButton( world._cmd_Clear, "button (disabled): clear") ## ) If_kluge( getattr_Expr(world, '_cmd_Clear_nontrivial'), ActionButton(world._cmd_Clear, "button: clear"), ActionButton(world._cmd_Clear, "button (disabled): clear", enabled=False) ) # works, though text change is so slow I suspect there's actually a highlighting or update bug making it appear even slower... # update 070109: the bug seems to be that as long as the mouse stays on the button, it remains highlighted with the old highlight form. ) return expr
class TestIterator_wrong_to_compare(InstanceMacro): """ variant of that which shows one Instance twice """ thing = Arg(Widget) # the only difference w1 = Instance(thing) # these Instances will be idempotent w2 = Instance(thing) _value = SimpleColumn( w1, w2) # show one instance twice pass
class TestIterator(InstanceMacro): """ simple iterator which makes two distinct instances of the same arg """ #e for debug, we should make args to pass to this which show their ipaths as text! thing = ArgExpr(Widget) w1 = Instance(thing) w2 = Instance(thing) # two distinct instances _value = SimpleColumn( w1, w2) pass
class make_Rect_PG(PropertyGroup): "property group contents for making a Rect" # note: classname includes make_Rect rather than MakeRect, # since it might not be the *only* PG for cmd_MakeRect, and it might be shared by other commands' PMs. # (not sure this is sensible) title = "Rect properties" delegate = SimpleColumn( ColorEdit(color_ref, label), ##e [could put color name into prefs, for now...] #e dimensions? (numeric textfields) co-update with its draggability? yes... #e someday: units, gridding, ref plane, ... ) pass
def ChoiceColumn( nchoices, dflt = 0, **kws): ##e should be an InstanceMacro, not a def! doesn't work to be customized this way. "#doc" #e nim: Column -- esp on list like this -- Column( map(...)) -- so use SimpleColumn return Apply( lambda stateref_expr, nchoices = nchoices, dflt = dflt, kws = kws: SimpleRow( # stateref_expr will be a Symbol when this lambda is run, to produce an expr, once only SimpleColumn( * map( ChoiceButton(choiceref = stateref_expr, **kws), range(nchoices) ) ), # choose TextRect( format_Expr( "choice is %%r (default %s)" % dflt, stateref_expr.value ), 1, 30) # show choice ), LocalVariable_StateRef(int, dflt) # LocalState, combining this and the Apply? # or, just a stateref to some fixed state somewhere... whose instance has .value I can get or set? use that for now. ##k is there any way to use the new-061203 State macro for this? )
class make_polyline3d_PG( PropertyGroup ): ###e call me ###e revise -- not clear it should refer to a pref #e rename? this name means "PG for the command make_<class>" ###e who supplies this? the command? i guess so. is it a local class inside it? or at least the value of an attr inside it? "contents of property manager group for a polyline3d which is being made" ###e needs some args that let it find that polyline3d or the making-command! ## arg = Arg() #e someday be able to automake this from higher-level contents... but returning a widget is always going to be a possibility # (see also comments in PM_from_groups about this) title = "Polyline Properties" ###e USE ME in PM_from_groups delegate = SimpleColumn( checkbox_pref(kluge_dragtool_state_prefs_key + "bla2", "closed loop?", dflt=False), # only gets closed when done -- ok?? ) pass
class PixelTester( InstanceOrExpr, DelegatingMixin ): # ought to be InstanceMacro but trying this alternate style just to see it # args testexpr = Arg(Widget2D) # instantiated right here, hope that's ok testname = Arg(str) # required for now, used to form filename # value filename = format_Expr("/tmp/%s.jpg", testname) delegate = SimpleColumn( TextRect( "saved image from PRIOR session, in blue box" ), # kluge: execute this first, so we read file before writing it Boxed(bordercolor=blue)(Image(filename)), Spacer(0.3), TextRect("live widget, in purple box"), Boxed(bordercolor=purple)(PixelGrabber(testexpr, filename)), ##e and put current session image here, for comparison, or put top on in a tab control for flicker test ) pass # end of class PixelTester
class PM_from_groups( DelegatingInstanceOrExpr ): ###e refile into demo_ui or so, and call it on [make_polyline3d_PG(somearg)] "Make a Property Manager UI from a list of groupbox content widgets (eg columns of field editors) and other info." # args groups = Arg(list_Expr) #e in future these groups need to come with more attrs, like group titles # (WAIT, they already do have a title attr which we don't use here!), # whether they're closable and if so whether initially closed... # and they might include their own Boxed already... # the type decl might say we want a list of PropertyGroupBoxes, # with autoconversion of ParameterGroups to those... message = Option( str, "(PM message goes here)" ) # this has to be already split into lines, for now; all indentation is stripped # formulae def _C_use_message(self): lines = self.message.split('\n') lines = [line.strip() for line in lines] lines = filter(None, lines) return '\n'.join(lines) use_message = _self.use_message # appearance message_box = Boxed(TextRect(use_message), gap=0, bordercolor=yellow) group_box_column = MapListToExpr( KLUGE_for_passing_expr_classes_as_functions_to_ArgExpr( Boxed), ###e change to a GroupBox, with a title from the group... groups, KLUGE_for_passing_expr_classes_as_functions_to_ArgExpr(SimpleColumn)) delegate = SimpleColumn( Left(message_box), Left(group_box_column), ) pass
class _MT_try2_node_helper(DelegatingInstanceOrExpr): """ [private helper expr class for MT_try2] One MT item view -- specific to one node, one whole MT, and one (possibly time-varying) position with it. """ # args ####e REORDER THEM node = Arg(ModelNode, doc = "any node that needs to be displayed in this MT") ###e NOTE: type coercion to this is nim; while that's true, we use helper functions like node_name(node) below; # once type coercion is implemented # (or simulated by hand by wrapping this arg with a helper expr like ModelTreeNode_trivial_glue), # we could instead use node.mt_name, etc.) mt = Arg(MT_try2, doc = "the whole MT view, in which we store MT items for nodes, and keep other central state or prefs if needed") name_suffix = Option(str, "") initial_open = Option(bool, False, doc = "initial value of boolean state 'open'; only used when this item is first created") ##e should ask the node itself for the initial value of open (e.g. so new groups, trying to start open, can do so), # and also advise it when we open/close it, in case it wants to make that state persistent in some manner # WARNING: compare to MT_try1 -- lots of copied code after this point # WARNING: the comments are also copied, and not yet reviewed much for their new context! (so they could be wrong or obs) ###k # state refs open = State(bool, initial_open) # other formulae ###e optim: some of these could have shared instances over this class, since they don't depend on _self; should autodetect this # 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)) openclose_spacer = Spacer(0.4) #e or Invisible(open_icon); otoh that's no simpler, since open_icon & closed_icon have to be same size anyway # the openclose icon, when open or close is visible (i.e. for openable nodes) openclose_visible = Highlightable( If( open, open_icon, closed_icon ), on_press = Set(open, not_Expr(open)), sbar_text = getattr_Expr( _self, '_e_serno') #070301 this permits finding out how often MT gets remade/shared # (results as of 070301: remade when main instance is, even if going back to a prior testexpr, out of _19i & _30i) ) openclose_slot = If( call_Expr(node_openable, node), openclose_visible, openclose_spacer ) if 0: # cross-highlighting experiment, 070210, but disabled since approach seems wrong (as explained in comment) yellow = DZ = 'need to import these' indicator_over_obj_center = Center(Rect(0.4, 0.4, yellow)) position_over_obj_center = node.center + DZ * 3 ###BUG: DZ does not point towards screen if trackballing was done ###STUB: # - should be drawn in a fixed close-to-screen plane, or cov plane (if obscuring is not an issue), # - so indicator size is constant in pixels, even in perspective view (I guess), # - also so it's not obscured (especially by node itself) -- or, draw it in a way visible behind obscuring things (might be a better feature) # - what we draw here should depend on what node is # - we also want to draw a line from type icon to node indicator (requires transforming coords differently) # - needs to work if node.center is not defined (use getattr_Expr - but what dflt? or use some Ifs about it) pointer_to_obj = DrawInCenter( Translate( indicator_over_obj_center, position_over_obj_center)) #bug: Translate gets neutralized by DrawInCorner [fixed now] ###BUG: fundamentally wrong -- wrong coord system. We wanted DrawInAbsCoords or really DrawInThingsCoords, # but this is not well-defined (if thing drawn multiply) or easy (see comments about the idea in projection.py). else: # What we want instead is to set a variable which affects how the obj is drawn. # If this was something all objs compared themselves to, then all objs would track its use (when they compared) # and therefore want to redraw when we changed it! Instead we need only the involved objs (old & new value) to redraw, # so we need a dict from obj to this flag (drawing prefs set by this MT). Maybe the app would pass this dict to MT_try2 # as an argument. It would be a dict of individually trackable state elements. (Key could be node_id, I guess.) # ### TRY IT SOMETIME -- for now, cross-highlighting experiment is disabled. pointer_to_obj = None # selection indications can use this node_is_selected = call_Expr( mt_node_selected, node) kluge_icon_color = If( node_is_selected, blue, green) sbar_format_for_name = If( node_is_selected, "%s (selected)", "%s") ###STUB for the type_icon ##e the Highlightable would be useful on the label too icon = Highlightable( Rect(0.4, 0.4, kluge_icon_color), ##stub; btw, would be easy to make color show hiddenness or type, bfr real icons work Overlay( Rect(0.4, 0.4, ave_colors(0.1, white, kluge_icon_color)), #070216 mix white into the color like DraggableObject does pointer_to_obj ), sbar_text = format_Expr( sbar_format_for_name, call_Expr(node_name, node) ) ) ##e selection behavior too label = DisplayListChunk( # added DisplayListChunk 070213 late -- does it speed it up? not much; big new-item slowness bug remains. retain, since doesn't hurt. TextRect( call_Expr(node_name, node) + name_suffix ) ) ###e will need revision to Node or proxy for it, so node.name is usage/mod-tracked ##e selection behavior too -- #e probably not in these items but in the surrounding Row (incl invis bg? maybe not, in case model appears behind it!) ##e italic for disabled nodes ##e support cmenu delegate = SimpleRow( CenterY(openclose_slot), SimpleColumn( SimpleRow(CenterY(icon), CenterY(label)), #070124 added CenterY, hoping to improve text pixel alignment (after drawfont2 improvements) -- doesn't work If( open, _MT_try2_kids_helper( call_Expr(node_kids, node) , _self.mt ), # 070218 added _self.mt -- always intended, first used now None # Note: this None used to be Spacer(0), due to a bug mentioned in a comment in ToggleShow.py # (but unfortunately not explained there -- it just says "I wanted None here, but it exposes a logic bug, # not trivial to fix, discuss in If or Column" -- my recollected bug-theory is described just below). # On 070302 I confirmed that None seems to work (even in testexpr_18i with a group of 2 chunks, plus two more below). # I don't fully know why it works, since I thought the bug was that SimpleColumn's None specialcase # didn't run, since the element was not None but the If, and then delegating lbox attrs to None didn't work. # (Fixable by using the newer If that evals, but for some reason that's not yet standard, I guess just because # I didn't have time to test it enough or think it through fully re ipath or instance caching or something.) # But as long as it works, use it -- ask Qs later. A recent perhaps-related change: None is allowed in drawkid. # (A memory scrap -- does instantiating None conceivably produce a spacer?? ###k) ) ) ) pass # end of class _MT_try2_node_helper
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
class main_ui_layout(DelegatingInstanceOrExpr): #e rename? is it not only the ui, but the entire app? (selection, files, etc) #e merge in the App obj from test.py, and the _recent_tests system in some form? # args (none yet) # internal state - permanent ###e note: when we reload and remake this instance, we'd prefer it if the world state stayed unchanged (as i presume it does) # but if the default_tool instance and toolstack state got remade. The lack of the latter has been confusing me # since changes to ui code aren't working. I think this is a difference between a ui and operations layer (should change) # vs model data layer (should not change even tho the op methods on it can change). So when I can put these things into layers # (not only State, but even Instance or attrs within them) and make those sensitive to reload, that will help. # In the meantime -- if I could kluge Instance and State to take an option to control this # (like index = exprs_globals.reload_counter) # it might help.... #####TRYIT SOMETIME, and BE CAREFUL UNTIL I DO. world = Instance(World()) default_tool = Instance(DefaultToolRun()) # internal state - varying toolstack = State(list_Expr, [ default_tool ]) # always has at least one tool on it; a stack of Instances not exprs # maybe the better term for this is something like command & subcommand current_tool = toolstack[ -1] # last tool on the stack is current; exiting it will pop the stack (Instance not expr) ##e (add a type-assertion (as opposed to type-coercion) primitive, so I can say "this is an Instance" in the code?) # NOTE: this is not strictly speaking a tool, but ONE RUN of a tool. That might be important enough to rename it for, # to ToolRun or maybe ActiveTool or RunningTool or ToolInUse or ToolBeingUsed... # [but note, obj might remain around on history or in Undo stack, even when no longer being used], # since we also have to deal with Tools in the sense of Tool Run Producers, eg toolbuttons. ###e # parts of the appearance registry = find_or_make_global_command_registry( ) ## None ###STUB, will fail -- ## AttributeError: 'NoneType' object has no attribute 'command_for_toolname' toolstack_ref = None ###STUB toolbar = Instance( MainToolbar(registry, ["Features", "Build", "Sketch"], toolstack_ref)) #e arg order? ###e args/opts for what tools to show -- maybe their cmdnames & it loads them from elsewhere #e add row of tool buttons, and flyout toolbar; use ChoiceRow?? the things should probably look pressed... # they might need cmenus (find out what the deal is with the cmenus i see in the ui mockup - related to flyouts? # yes, it's like this: main tools have cmenus with subtools, and if you pick one, main tool and its subtool both look pressed # I'll need new specialized controls.py classes for these; new super Control for all kinds of controls?? (not sure why...) propmgr = SimpleColumn( TextRect( "(property manager)"), #e possibly to become a tab control tab DebugPrintAttrs( current_tool.property_manager ) # must be None if we don't want one visible; otherwise an Instance ###BUG: DebugPrintAttrs shows that it's a spacer -- I guess IorE turns None into one when it instantiates? Make it a false one?? ) mt = SimpleColumn( TextRect( "(model tree)" ), #e possibly to become a tab control tab, but only when we're in the left channel MT_try2(world) #e rename to "Feature Manager" ?? ##e soon, MT should be not on whole world but on model or cur. part, a specific obj in the world ) graphics_area = _self.world ##e ditto for what we show here, except it might not be the exact same object, and it will really be shown in a way # that depends on both the current display style and the current tool (command & subcommand) graphics_area_topright_buttons = current_tool.graphics_area_topright_buttons # overall appearance delegate = Overlay( # stuff in the corners -- note, these don't use the corner constants for standalone tests like PM_CORNER DrawInCorner(corner=UPPER_LEFT)( SimpleColumn( toolbar, #e add tab control SimpleRow( If( current_tool.property_manager, Top(propmgr), None ), #k None?? prob ok now, see demo_MT comment 070302 ###k Top(mt) ), #e actually we'd then put a splitter & glpane-like-thing... #e anything just below the propmgr? )), DrawInCorner(corner=UPPER_RIGHT) ( ##e of graphics area, not entire screen... graphics_area_topright_buttons ### WRONG, these should go under the main toolbar area on the right # (but we don't yet have any 2dwidgets which expand to fill the available space, except DrawInCorner of entire screen) # (this won't matter once the toolbar is done entirely in Qt, so we don't need to correct it for now) ), #e other corners? "... an area (view) on the right side # of the main window for accessing the part library, on-line documentation, etc" # the main graphics area #e [this too ought to go under the toolbar and to the right of the propmgr, but that can wait until they're fully in Qt] graphics_area) pass
import foundation.env as env polyline = env.prefs.get(kluge_dragtool_state_prefs_key + "bla", False) #070223 new hack if polyline: return "polyline" # for this kluge, let the stored value be False or True for whether it's drag drag = env.prefs.get(kluge_dragtool_state_prefs_key, kluge_dragtool_state_prefs_default) return drag and 'drag' or 'draw' kluge_dragtool_state() # set the default val kluge_dragtool_state_checkbox_expr = SimpleColumn( # note, on 061215 late, checkbox_pref was replaced with a better version, same name checkbox_pref(kluge_dragtool_state_prefs_key, "drag new nodes?", dflt=kluge_dragtool_state_prefs_default), checkbox_pref(kluge_dragtool_state_prefs_key + "bla", "some other pref"), ) def demo_drag_toolcorner_expr_maker(world): #070106 improving the above # given an instance of World, return an expr for the "toolcorner" for use along with GraphDrawDemo_FixedToolOnArg1 (on the same World) expr = SimpleColumn( checkbox_pref(kluge_dragtool_state_prefs_key, "drag new nodes?", dflt=kluge_dragtool_state_prefs_default), checkbox_pref(kluge_dragtool_state_prefs_key + "bla", "make polyline?", dflt=False), checkbox_pref(kluge_dragtool_state_prefs_key + "bla2", "(make it closed?)",