Пример #1
0
class test_polyline_drag(State_preMixin, ExampleCommand):
    # class constants needed by mode API for example commands
    commandName = 'test_polyline_drag-commandName'
    default_mode_status_text = "test_polyline_drag"
    featurename = "Prototype: Example Polyline Drag Command"
    ##    PM_class = test_polyline_drag_PM

    # tracked state
    rubberBand_enabled = State(
        bool, False, doc="whether we're rubberbanding a new segment now")
    # TODO:
    ### grab a polyline object from an example file in exprs ### (the one that has a closed boolean and can draw in 3d)
    ### have a list of them, we're rubberbanding last segment of last one...

    lastSegmentStart = ORIGIN + 6 * DY  # stub
    lastSegmentEnd = State(
        Point,
        doc="endpoint of last segment; only meaningful when rubberBand_enabled"
    )
    # note: these might be redundant with some points in a polyline object;
    # should they be aliases into one?

    rubberBandDrawable = If_expr(
        rubberBand_enabled,
        Line(lastSegmentStart, lastSegmentEnd, red, thickness=4), NullDrawable)

    whatWeDraw = Instance(rubberBandDrawable)

    # init methods

    def __init__(self, glpane):
        # not sure why this method is needed, see comment in test_connectWithState.__init__
        super(test_polyline_drag, self).__init__(glpane)
        ExampleCommand.__init__(self, glpane)
        return

    def Draw(self):
        super(test_polyline_drag, self).Draw()  #k
        self.whatWeDraw.draw()
        return

    def leftDown(self, event):
        print "leftDown"
        # TODO:
        # get the point (mouseray in plane)
        # make a real point there (or mark it as real, if we have a point object for it already)
        # (so it has a blue dot of its own)
        # update self.rubberBand_enabled
        # STUB:
        self.rubberBand_enabled = True
        self.lastSegmentEnd = self.lastSegmentStart + 3 * DX
        ExampleCommand.leftDown(self, event)
        ### will this prevent this error in mouse release:
        ## AttributeError: 'test_polyline_drag' object has no attribute 'LMB_press_event'
        ##   [GLPane.py:1805] [selectAtomsMode.py:899]
        return

    pass
Пример #2
0
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
Пример #3
0
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
Пример #4
0
class DnaStrand_ResizeHandle(DraggableHandle_AlongLine):
    """
    Provides a resize handle for editing the length of an existing Dna Strand.
    """

    #Handle color will be changed depending on whether the handle is grabbed
    # [bruce 080409 revised some details of this to fix bug 2747]

    handleColor = Option(Color, purple) # formula from caller
        # (in current usage, a state variable in caller)

    handleIsGrabbed = State(Boolean, False)
        # Note: this might not be needed if we passed more args to
        # Highlightable (namely, the appearance when pressed);
        # that would also be more reliable, since as it is, any failure for
        # on_release to be called would leave the handle stuck in the
        # grabbed state; client code would be wise to sometimes reset
        # this state. Also, it seems rare to ever see this selection color
        # since the handle is usually highlighted and yellow while dragging it.
        # [Depending on the highlight and selection drawing mode.  Russ 080530]
        # So this state could probably just be removed, with all uses of
        # _currentHandleColor changes to uses of handleColor.
        # [bruce 080409]

    _currentHandleColor = If_expr( handleIsGrabbed,
                                   env.prefs[selectionColor_prefs_key],
                                   _self.handleColor)

    #The caller-specified formula that determines the radius (of the sphere) of this handle.
    #See DnaStrand_EditCommand._determine_resize_handle_radius() for more
    #details
    sphereRadius = Option(Width, 1.5)

    #Appearance of the handle. (note that it uses all the code from exprs module
    # and needs more documentation there).
    #See exprs.Rect.Sphere for definition of a drawable 'Sphere' object.

    appearance = Overlay(
            Sphere(_self.sphereRadius,
                   _self._currentHandleColor,
                   center = ORIGIN + _self.direction * 3.0 * _self.sphereRadius),

            Cylinder((ORIGIN,
                      ORIGIN + _self.direction * 2.2 * _self.sphereRadius),
                      0.6 * _self.sphereRadius,
                      _self._currentHandleColor))

    #Handle appearance when highlighted
    # [this probably doesn't need to be an Option, since the client never
    #  passes it [bruce 080409 comment]]
    HHColor = env.prefs[hoverHighlightingColor_prefs_key]
    appearance_highlighted = Option(
        Drawable,
        Overlay(
            Sphere(_self.sphereRadius,
                   HHColor,
                   center = ORIGIN + _self.direction * 3.0 * _self.sphereRadius),

            Cylinder((ORIGIN,
                      ORIGIN + _self.direction * 2.2 * _self.sphereRadius),
                     0.6* _self.sphereRadius ,
                     HHColor)),
            doc = "handle appearance when highlighted")


    #Stateusbar text. Variable needs to be renamed in superclass.
    sbar_text = Option(str,
                       "Drag the handle to resize the strand",
                       doc = "Statusbar text on mouseover")

    #Command object specified as an 'Option' during instantiation of the class
    #see DnaSegment_EditCommand class definition.
    command =  Option(Action,
                      doc = 'The Command which instantiates this handle')

    #Current position of the handle. i.e. it is the position of the handle
    #under the mouse. (its differert than the 'orifinal position)
    #This variable is used in self.command.graphicsMode to draw a rubberband
    #line  and also to specify the endPoint2 of the structure while modifying
    #it. See DnaSegment_EditCommand.modifyStructure for details.
    if _self.origin is not None:
        currentPosition = _self.origin + _self.direction * _self.height_ref.value
    else:
        currentPosition = ORIGIN


    #Fixed end of the structure (self.command.struct) ..meaning that end won't
    #move while user grabbs and draggs this handle (attached to a the other
    #'moving endPoint) . This variable is used to specify endPoint1 of the
    #structure while modifyin it.  See DnaSegment_EditCommand.modifyStructure
    #and self.on_release for details.
    fixedEndOfStructure = Option(Point,
                                 V(0, 0, 0))

    #If this is false, the 'highlightable' object i.e. this handle
    #won't be drawn. See DraggableHandle.py for the declararion of
    #the delegate(that defines a Highlightable) We define a If_Exprs to check
    #whether to draw the highlightable object.
    should_draw = State(bool, True)

    def ORIG_NOT_USED_hasValidParamsForDrawing(self):
        """
        NOT USED AS OF 2008-04-02
        Returns True if the handles origin and direction are not 'None'.

        @see: DnaStrand_GraphicsMode._draw_handles() where the caller
              uses this to decide whether this handle can be drawn without
              a problem.
        """
        #NOTE: Better to do it in the drawing code of this class?
        #But it uses a delegate to draw stuff (see class Highlightable)
        #May be we should pass this method to that delegate as an optional
        #argument -- Ninad 2008-04-02
        if self.origin is None or self.direction is None:
            return  False

        return True


    def hasValidParamsForDrawing(self):
        """
        Returns True if the handles origin and direction are not 'None'.

        @see: DnaStrand_GraphicsMode._draw_handles() where the caller
              uses this to decide whether this handle can be drawn without
              a problem.

        """

        #NOTE: Better to do it in the drawing code of this class?
        #But it uses a delegate to draw stuff (see class Highlightable)
        #May be we should pass this method to that delegate as an optional
        #argument -- Ninad 2008-04-02

        #@Bug: Create a duplex; Enter Dna strand edit command,
        # then shorten it such that it removes some bases of the strand from the
        #original duplex. Hit undo; click on the right handle, and shorten it again
        #sometimes it gives a traceback. in drawing the highlightable
        #this could be because self.should_draw flag is not getting updated.


        #NOTES: If this method is used, you will also need to define the
        #delegate in class DraggableHandle as --
        #delegate = If_Exprs(_self.should_draw, Highlightable(....))
        if self.origin is None or self.direction is None:
            self.should_draw = False
        else:
            self.should_draw = True

        return self.should_draw


    def on_press(self):
        """
        Actions when handle is pressed (grabbed, during leftDown event)
        @see: B{SelectChunks.GraphicsMode.leftDown}
        @see: B{DnaStrand_EditCommand.grabbedHandle}
        @see: B{DnaStrand_GraphicsMode.Draw} (which uses some attributes of
             the current grabbed handle of the command.
        @see: B{DragHandle_API}
        """
        #Change the handle color when handle is grabbed. See declaration of
        #self.handleColor in the class definition.

        ## self._currentHandleColor = env.prefs[selectionColor_prefs_key]
        self.handleIsGrabbed = True

        #assign 'self' as the curent grabbed handle of the command.
        self.command.grabbedHandle = self

    def on_drag(self):
        """
        Method called while dragging this handle .
        @see: B{DragHandle_API}
        """
        pass
        #The following call is disabled. Instead updating this spinbox
        #is done by the command.getCursorText method . See that method for
        #details
        ##self.command.update_numberOfBases()

    def on_release(self):
        """
        This method gets called during leftUp (when the handle is released)
        @see: B{DnaStrand_EditCommand.modifyStructure}
        @see: self.on_press
        @see: B{SelectChunks.GraphicsMode.leftUp}
        @see: B{DragHandle_API}
        """
        ## self._currentHandleColor = self.handleColor
        self.handleIsGrabbed = False

        if self.command and hasattr(self.command, 'modifyStructure'):
            self.command.modifyStructure()
            #Clear the grabbed handle attribute (the handle is no longer
            #grabbed)
            self.command.grabbedHandle = None
Пример #5
0
class MakeCrossovers_Handle(DelegatingInstanceOrExpr):

    should_draw = State(bool, True)
    radius = 0.8

    point1 = Arg(Point)
    point2 = Arg(Point)

    scale = Arg(float)

    crossoverSite_marker = Option(
        Action,
        doc='The CrossoverSite Marker class which instantiates this handle')

    #Command object specified as an 'Option' during instantiation of the class
    #see DnaSegment_EditCommand class definition.
    command = Option(Action, doc='The Command which instantiates this handle')

    crossoverPairs = Option(tuple, ())

    #Stateusbar text. Variable needs to be renamed in superclass.
    sbar_text = Option(str,
                       "Click on the handle to create this crossover",
                       doc="Statusbar text on mouseover")

    delegate = If_expr(
        _self.should_draw,
        Highlightable(Overlay(
            Cylinder((call_Expr(_self.crossoverPairs[0].posn),
                      call_Expr(_self.crossoverPairs[3].posn)),
                     radius=radius,
                     color=silver),
            Cylinder((call_Expr(_self.crossoverPairs[1].posn),
                      call_Expr(_self.crossoverPairs[2].posn)),
                     radius=radius,
                     color=silver)),
                      Overlay(
                          Cylinder((call_Expr(_self.crossoverPairs[0].posn),
                                    call_Expr(_self.crossoverPairs[3].posn)),
                                   radius=radius,
                                   color=banana),
                          Cylinder((call_Expr(_self.crossoverPairs[1].posn),
                                    call_Expr(_self.crossoverPairs[2].posn)),
                                   radius=radius,
                                   color=banana)),
                      on_press=_self.on_press,
                      on_release=_self.on_release,
                      sbar_text=sbar_text))

    ##delegate = If_expr(_self.should_draw,
    ##Highlightable(Cylinder((point1, point2),
    ##radius = radius,
    ##color = silver),
    ##Cylinder((point1, point2),
    ##radius = radius,
    ##color = banana),
    ##on_press = _self.on_press,
    ##on_release = _self.on_release))

    ##delegate = \
    ##If_expr(
    ##_self.should_draw,
    ##Highlightable(Arrow(
    ##color = silver,
    ##arrowBasePoint = point1,
    ####tailPoint = norm(vector)*1.0,
    ##tailPoint = point2,
    ##radius = radius,
    ##scale = scale),

    ##Arrow(
    ##color = banana,
    ##arrowBasePoint =  point1,
    ####tailPoint = norm(vector)*1.0,
    ##tailPoint =  point2,
    ##radius = radius,
    ##scale = scale),
    ##on_press = _self.on_press,
    ##on_release = _self.on_release ) ) #

    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

    def on_press(self):
        pass

    def on_release(self):
        self.command.makeCrossover(self.crossoverPairs)
        self.crossoverSite_marker.removeHandle(self)