def on_drag_bg(self): # note: so far, anyway, called only for drag after click on empty space, not from drag after click on existing node point = self.current_event_mousepoint() lastnode = self.newnode # btw nothing clears this on mouseup, so in theory it could be left from a prior drag ## try: ## lastipath = lastnode.ipath[0] ## except: ## lastipath = -1 ## # print "on_drag_bg %d" % lastipath, point### # this shows no error in retaining correct lastnode -- that's not the bug ## print "on_drag_bg" newpos = point + DZ * DZFUZZ # used for different things, depending what = kluge_dragtool_state() ###IMPLEM better if what == 'draw': # make a blue dot showing the drag path, without moving the main new node (from the click) node_expr = Vertex(newpos, Center(Rect(0.1, 0.1, blue))) self.world.make_and_add( node_expr, type="dot" ) #070206 added type = "dot" -- note, not deducible from the expr!! elif what == 'polyline': if not lastnode: print "bug: no self.newnode!!!" else: if not isinstance(lastnode, polyline): lastnode = self.newnode = self.world.make_and_add( polyline(lastnode), type="polyline") lastnode.add_point(newpos) elif what == 'drag': # drag the new node made by the click if not lastnode: print "bug: no self.newnode!!!" else: lastnode.pos = newpos pass return
class NativeImage( DelegatingInstanceOrExpr ): #070304 [works (imperfectly? see comments there) in testexpr_11u6] """ Show an image in its native size and aspect ratio -- that is, one image pixel == one texture pixel == one screen pixel, when the local coordsys is the standard viewing coordsys. Note: callers are advised to enclose this inside Highlightable, at least until we add local glnames to fix the bug of all bareMotion over non-Highlightable drawing causing redraws. """ # args filename = Arg(str, "x") #e better type, eg Filename? ###BUG: ought to take all options and pass them on to Image [070403 comment] # formulae [non-public in spite of the names] im1_expr = Image(filename, use_mipmaps=True, ideal_width=-1, ideal_height=-1) # customize Image to use native texture size (but without controlling the aspect ratio for display) ###e consider also including the options that IconImage does, or options passed by caller # (but passing general opts (like python **kws syntax can do) is nim in the exprs language) im1 = Instance( im1_expr) # grab an actual image so we can find out its native size th = im1._texture_holder # gets its _texture_holder object imops = th._image # get its nEImageOps object # appearance delegate = im1_expr( size=Center(Rect(imops.orig_width * PIXELS, imops.orig_height * PIXELS))) # (implem note: this customizes im1_expr options even though its args (filename) are already supplied. # That used to give a warning but apparently doesn't now. If it does again someday, # it's easy to fix here -- just give filename in each instantation rather than in im1_expr.) pass
def on_press(self): point = self.current_event_mousepoint() 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! #e maybe scrap it here, and instead change class polyline3d to always draw itself closer to the screen # than its stored coords, but store coords identical to those of the underlying model object -- # use a globally available displist (nim) for translating closer to the user -- hmm, that has to be different # for each rotational environment you might be inside! So only the graphical env knows its name... node_expr = Vertex(newpos, Center(Rect(0.2, 0.2, red))) newnode = self.world.make_and_add( node_expr, type="Vertex") #070206 added type = "Vertex" ###e may want to make, but not add... let it be a kid of the polyline3d self.newnode = newnode return
class test_connectWithState(State_preMixin, ExampleCommand): # class constants needed by mode API for example commands commandName = 'test_connectWithState-commandName' default_mode_status_text = "test_connectWithState" featurename = "Prototype: Test connectWithState" PM_class = test_connectWithState_PM # tracked state -- this initializes specially defined instance variables # which will track all their uses and changes so that connectWithState # works for them: cylinderVertical = State(bool, False) cylinderWidth = State(float, CYLINDER_WIDTH_DEFAULT_VALUE) # TODO: soon this will be the only use of this constant, so it can be inlined cylinderColor = State('color-stub', pink) # type should be Color (nim), but type is not yet used # note: you can add _e_debug = True to one or more of these State definitions # to see debug prints about some accesses to this state. GraphicsMode_class = _test_connectWithState_GM # init methods def __init__(self, glpane): # I don't know why this method is needed. ##### REVIEW (super semantics), FIX or clean up super(test_connectWithState, self).__init__(glpane) # State_preMixin.__init__ ExampleCommand.__init__(self, glpane) # (especially this part) return ## def __init__(self, glpane): ## super(test_connectWithState, self).__init__(glpane) #### # that only calls some mode's init method, #### # so (for now) call this separately: #### IorE_guest_mixin.__init__(self, glpane) ## return # exprs-based formulae (and some compute methods) direction = If_expr( cylinderVertical, DY, DX ) def _C_width_direction(self): """ compute self.width_direction """ # Note: to do this with a formula expr instead # would require cross_Expr to be defined, # and glpane.lineOfSight to be tracked. return cross( self.direction, self.env.glpane.lineOfSight ) width_direction = _self.width_direction # so it can be used in formulae below # stub for handle test code [070912] widthHandleEnabled = True # stub ## widthHandle = Instance(Rect()) # stub h_offset = 0.5 + 0.2 # get it from handle? nah (not good if that changes with time); just make it fit. # or we could decide that handles ought to have useful fixed bounding boxes... ## widthHandle = Instance(Translate(Center(Rect(0.5)), ## width_direction * (cylinderWidth / 2.0 + h_offset) )) #stub widthHandle = Instance( DraggableHandle_AlongLine( appearance = Center(Rect(0.5, 0.5, white)), ### REVIEW: # Can't we just replace the following with something based on the formula for the position, # width_direction * (cylinderWidth / 2.0 + h_offset) # ? # As it is, I have to manually solve that formula for origin and direction to pass in, # i.e. rewrite it as # position = origin + direction * cylinderWidth ## height_ref = cylinderWidth, ###WRONG ## height_ref = ObjAttr_StateRef( _self, 'cylinderWidth'), ## ## AssertionError: ObjAttr_StateRef fallback is nim -- needed for S._self height_ref = call_Expr( ObjAttr_StateRef, _self, 'cylinderWidth'), # guess at workaround; #e we need a more principled way! ### REVIEW: efficient enough? (guess: overhead only happens once, so yes) # could we say instead something like: height_ref = Variable(cylinderWidth) ?? Or VariableRef? Or StateRef_to ? origin = width_direction * h_offset, # note: also includes cylinder center, but that's hardcoded at ORIGIN direction = width_direction / 2.0, sbar_text = "cylinder width", ### TODO: make it a formula, include printed value of width? range = (0.1, 10), ### TODO: DraggableHandle_AlongLine should take values from the stateref if this option is not provided; # meanwhile, we ought to pass a consistent value! )) # Note: the Instance is required; but I'm not sure if it would be # if we were using a fuller exprs superclass or init code. [bruce 070912] def cmd_Bigger(self): self.cylinderWidth += 0.5 set_cylinder_height( cylinder_height() + 0.5) # TODO: enforce maxima return def cmd_Smaller(self): self.cylinderWidth -= 0.5 set_cylinder_height( cylinder_height() - 0.5) # enforce minima (###BUG: not the same ones as declared in the PM) ### REVISE: min & max should be declared in State macro and (optionally) enforced by it if self.cylinderWidth < 0.1: self.cylinderWidth = 0.1 if cylinder_height() < 0.1: set_cylinder_height(0.1) return pass
class DraggableHandle_AlongCircle(DelegatingInstanceOrExpr): """ A kind of draggable handle which can be dragged along a line to change the value of a single floating point parameter (representing position along the line, using a scale and origin determined by our arguments). ### TODO: add epydoc parameters to this docstring? not sure that will work for a class! Maybe we need to synthesize those (from the doc options below) into a fake __init__ method for its sake?? """ # == args and options # options for appearance of handle appearance = Option( Drawable, Center(Rect(0.2, 0.2, white)), doc = "appearance, when not highlighted") appearance_highlighted = Option( Drawable, appearance, doc = "appearance, when highlighted") sbar_text = Option(str, "draggable handle along circle", doc = "statusbar text on mouseover") # state variable controlled by dragging rotationDistanceRef = Option(StateRef, doc = "stateref to a dragged disctance variable") # action options, for Highlightable to do after the ones that come from # DragBehavior_AlongLine [new feature of this and Highlightable, 080129] on_press = Option(Action) on_drag = Option(Action) on_release = Option(Action) on_release_in = Option(Action, on_release) on_release_out = Option(Action, on_release) on_doubleclick = Option(Action) #origin of the handle itself origin = Option( Point, ORIGIN) # Center of the circle whose perimeter serves as a path along which to # drag center = Option( Point, ORIGIN) #Axis of the circle. axis = Option( Vector, DX, doc = "vector giving direction and scale") #radius Vector radiusVector = Option( Vector, DX, doc = "vector giving direction and scale") #angle range for the rotation range_for_rotation = Option(tuple_Expr, None, doc = "range limit of angle (tuple)") # == internal instances and formulae (modified from test_statearray_3.py) _drag_handler = Instance( DragBehavior_AlongCircle( _self._delegate, rotationDistanceRef, origin, center, axis, radiusVector, range_for_rotation = range_for_rotation)) #QUESTION: Should the 'RotateTranslate' transform from exprs.transforms be #used here? -- Ninad 2008-02-13 delegate = \ Highlightable( Translate( appearance, _drag_handler._rotation #k ok?? only if that thing hangs around even in between drags, i guess! #e #k not sure if this code-commoning is good, but it's tempting. hmm. ), highlighted = Translate( appearance_highlighted, _drag_handler._rotation ), sbar_text = sbar_text, behavior = _drag_handler, on_press = _self.on_press, on_drag = _self.on_drag, # (note: no need to pass on_release) on_release_in = _self.on_release_in, on_release_out = _self.on_release_out, on_doubleclick = _self.on_doubleclick, ) pass # end of class
class DraggableHandle_AlongLine(DelegatingInstanceOrExpr): ### TODO: all options might need renaming! replace "height" everywhere. """ A kind of draggable handle which can be dragged along a line to change the value of a single floating point parameter (representing position along the line, using a scale and origin determined by our arguments). ### TODO: add epydoc parameters to this docstring? not sure that will work for a class! Maybe we need to synthesize those (from the doc options below) into a fake __init__ method for its sake?? """ # == args and options # options for appearance of handle appearance = Option( Drawable, Center(Rect(0.2, 0.2, white)), doc = "our appearance, when not highlighted") ###e take other args of Highlightable? appearance_highlighted = Option( Drawable, appearance, doc = "our appearance, when highlighted") sbar_text = Option(str, "draggable handle", doc = "our statusbar text on mouseover") # state variable controlled by dragging height_ref = Option(StateRef, doc = "stateref to a height variable") # TODO: rename, redoc range = Option(tuple_Expr, None, doc = "range limit of height (tuple)") ### MAYBE: RENAME to avoid conflict with python range in this code ### TODO: take values from the stateref if this option is not provided # action options, for Highlightable to do after the ones that come from # DragBehavior_AlongLine [new feature of this and Highlightable, 080129] on_press = Option(Action) on_drag = Option(Action) on_release = Option(Action) on_release_in = Option(Action, on_release) on_release_out = Option(Action, on_release) on_doubleclick = Option(Action) # line along which to drag it, and how to interpret the state as a position along that line (origin and scale) origin = Option( Point, ORIGIN) direction = Option( Vector, DX, doc = "vector giving direction and scale") # providing a default value is mainly just for testing #If this is false, the 'highlightable' object i.e. this handle #won't be drawn. The delegate (that defines a Highlightable) #We define an If_expr to check whether to draw the highlightable object. #[by Ninad] # [this should probably be revised, with hasValidParamsForDrawing replaced # with an overridable compute method, for robustness -- current implem # is suspected of causing tracebacks from insufficient update of this # state. Need to review whether methodname needs to be hasValidParamsForDrawing # to conform with any API. -- bruce 080409 comment] should_draw = State(bool, True) # == internal instances and formulae (modified from test_statearray_3.py) _drag_handler = Instance( DragBehavior_AlongLine( _self._delegate, height_ref, call_Expr(Ray, origin, direction), # note: we need call_Expr since Ray is an ordinary class, not an expr! ###FIX range = range )) # note: _drag_handler is also being used to compute the translation from the height, even between drags. #@see: DnaStrand_ResizeHandle.hasValidParamsForDrawing #@see: definition of State attr should_draw delegate = \ If_expr( _self.should_draw, Highlightable( Translate( appearance, _drag_handler._translation #k ok?? only if that thing hangs around even in between drags, i guess! #e #k not sure if this code-commoning is good, but it's tempting. hmm. ), highlighted = Translate( appearance_highlighted, _drag_handler._translation ), sbar_text = sbar_text, behavior = _drag_handler, on_press = _self.on_press, on_drag = _self.on_drag, # (note: no need to pass on_release) on_release_in = _self.on_release_in, on_release_out = _self.on_release_out, on_doubleclick = _self.on_doubleclick ) #end of Highlightable ) #end of If_expr def hasValidParamsForDrawing(self): """ Overridden in subclasses. Default implementation returns True if this object (the highlightable) can be drawn without any known issues @see: DnaStrand_ResizeHandle.hasValidParamsForDrawing for more notes. """ self.should_draw = True return self.should_draw pass # end of class
class DraggablyBoxed( Boxed ): # 070316; works 070317 [testexpr_36] before ww,hh State or resizable, and again (_36b) after them # inherit args, options, formulae from Boxed thing = _self.thing ###k WONT WORK unless we kluge ExprsMeta to remove this assignment from the namespace -- which we did. ###e not sure this is best syntax though. attr = _super.attr implies it'd work inside larger formulae, but it can't; # attr = Boxed.attr might be ok, whether it can work is not reviewed; it too might imply what _super does, falsely I think. extra1 = _self.extra1 borderthickness = _self.borderthickness rectframe = _self.rectframe # a pure expr # new options resizable = Option(bool, False, doc="whether to make it resizable at lower right") # works 070317 10pm (testexpr_36b) except for a few ###BUGS [updated info 070318 7pm]: # + [fixed] the wrong corner resizes (top right) (logic bug) # + [fixed] resizer doesn't move (understood -- wrong expr for its posn; commented below) # - negative sizes allowed (missing feature - limit the drag - need new DragBehavior feature) # - no clipping to interior of rectframe (missing feature - draw something clipped) # - perspective view ought to work, but entirely ###UNTESTED. # also, cosmetic bugs: # - resizer doesn't follow mouse in rotated coordsys, even in ortho view (though it's still useable). # (This is not surprising -- we're using the wrong kind of DragBehavior as a simple kluge.) # - the resizer is ugly, in shape & color. clipped = Option( bool, False, doc="###doc") #070322 new feature ### make True default after testing? # state # WARNING: due to ipath persistence, if you revise dflt_expr you apparently need to restart ne1 to see the change. ## ww = State(Width, thing.width + 2 * extra1) # replaces non-state formula in superclass -- seems to work ## hh = State(Width, thing.height + 2 * extra1) ## # now we just need a way to get a stateref to, effectively, the 3-tuple (ww,hh,set-value-discarder) ... instead, use whj: whj = State(Vector, V_expr(thing.width + 2 * extra1, -thing.height - 2 * extra1, 0)) #e not sure this is sound in rotated coordsys translation = State(Vector, ORIGIN) # override super formulae ww = whj[0] # seems to work hh = neg_Expr( whj[1] ) # negative is needed since drag down (negative Y direction) needs to increase height # (guess: neg_Expr wouldn't be needed if we used an appropriate new DragBehavior in resizer, # rather than our current klugy use of SimpleDragBehavior) # appearance rectframe_h = Instance( Highlightable( ## rectframe(bordercolor=green),####### cust is just to see if it works -- it doesn't, i guess i sort of know why ##bug: __call__ of <getattr_Expr#8243: (S._self, <constant_Expr#8242: 'rectframe'>)> with: () {'bordercolor': (0.0, 1.0, 0.0)} ##AssertionError: getattr exprs are not callable TopLeft(rectframe), #e different colored hover-highlighted version?? for now, just use sbar_text to know you're there. sbar_text= "draggable box frame", # this disappears on press -- is that intended? ###k behavior=SimpleDragBehavior( # arg1: the highlightable _self.rectframe_h, # arg2: a write-capable reference to _self.translation ## fails - evalled at compile time, not an expr: LvalueFromObjAndAttr( _self, 'translation'), ###BUG: why didn't anything complain when that bug caused the state value to be an add_Expr, not a number-array? call_Expr(LvalueFromObjAndAttr, _self, 'translation'), #e alternate forms for this that we might want to make work: # - getattr_StateRef(_self, 'translation') # simple def of the above # - StateRef_for( _self.translation ) # turns any lvalue into a stateref! Name is not good enough, though. ))) resizer = Instance( Highlightable( Center(Rect(extra1, extra1)), #e also try BottomRight highlighted=Center(Rect(extra1, extra1, white)), pressed=_my.highlighted, sbar_text="resize the box frame", behavior=SimpleDragBehavior( _self.resizer, call_Expr(LvalueFromObjAndAttr, _self, 'whj')))) ###BUG: in Boxed, rectframe comes first, so lbox attrs are delegated to it. We should do that too -- # but right now we draw it later in order to obscure the thing if they overlap. With clipping we won't need that -- # but without clipping we will. If the latter still matters, we need a version of Overlay with delegation != drawing order, # or, to delegate appearance and layout to different instances ourselves. (Or just to define new formulae for lbox -- easiest.) #e drawme = Instance( Overlay( If( clipped, Clipped( thing, planes=[ call_Expr(clip_to_right_of_x0, -thing.bleft - extra1 + ww - borderthickness), # note: the (- borderthickness) term makes the clipping reach exactly # to the inner rectframe edge. Without it, clipping would reach to the outer edge, # which for 3d objects inside the frame can cause them to obscure it. # (Other interesting values are (- extra1) and (- borderthickness/2.0), # but they both look worse, IMHO.) call_Expr(clip_below_y0, thing.btop + extra1 - hh + borderthickness) ]), thing, ), Translate(rectframe_h, V_expr(-thing.bleft - extra1, thing.btop + extra1)), If( resizable, ## Translate( resizer, V_expr( thing.bright + extra1, - thing.bbottom - extra1)) ###WRONG - this posn is fixed by thing's lbox dims, not affected by ww, hh; # will the fix be clearer if we use a TopLeft alignment expr? # It'd be hard to use it while maintaining thing's origin for use by external alignment -- # but maybe there's no point in doing that. Translate( resizer, V_expr(-thing.bleft - extra1 + ww, thing.btop + extra1 - hh))))) _value = Translate( drawme, ## DisplayListChunk( drawme), ###k this DisplayListChunk might break the Highlightable in rectframe_h ##### translation) pass # end of class DraggablyBoxed
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
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