Пример #1
0
 def _SliderOnMotion(self, event):
     
     if not self._sliderDown:
         return 
     
     # Calc current position in normalized units
     x0 = self._getNormalizedCurrentPos(event)
     
     # Reset before updating
     self._range = Range(self._refRange)
     
     # New normalized position
     dx =  x0 + self._sliderRefx
     offset = self._fullRange.min
     
     if self._sliderDown == 1:
         # Move on left edge
         self._range.min = self._fullRange.range * dx + offset
     elif self._sliderDown == 3:
         # Move on right edge
         self._range.max = self._fullRange.range * dx + offset
     elif self._sliderDown == 2:
         # Move whole slider
         ra2 = self._refRange.range / 2.0 
         mi = self._fullRange.range * dx - ra2 + offset
         ma = self._fullRange.range * dx + ra2 + offset
         self._range.Set(mi,ma)
     
     # Limit and update
     self._limitRangeAndSetText()
     self._eventSliding.Set()
     self._eventSliding.Fire()
     self.Draw()
Пример #2
0
 def __init__(self, parent):
     Box.__init__(self, parent)
     
     # init size
     self.position.w = 300
     self.position.h = 40
     
     # Slider specific stuff
     self._fullRange = Range(0,1)
     self._range = Range(0,1)
     self._refRange = Range(0,1) # For sliding
     self._showTicks = False
     
     # Set bgcolor and edge
     self.bgcolor = (0.6, 0.8, 0.6)
     self._frontColor = 0.5, 0.7, 0.9
     self.edgeWidth = 1
     
     # A slider should respond to mouse
     self.hitTest = True
     
     # Create label centered at the box
     self._label = Label(self)
     self._label.position = 0,0,1,1
     self._label.halign = 0
     self._label.bgcolor = None
     
     # State variables
     self._isOver = False
     self._sliderDown = False
     self._sliderRefx = 0.0
     
     # Pool of labels for tickmarks, to reuse them
     self._wobjects = [] # So we can have Text objects
     self._labelPool = {}
     
     # Calculate dots now
     self._SliderCalcDots()
     
     # Create new events
     self._eventSliding = BaseEvent(self)
     self._eventSliderChanged = BaseEvent(self)
     
     # To changes appearance on mouse over
     self.eventEnter.Bind(self._SliderOnEnter)
     self.eventLeave.Bind(self._SliderOnLeave)
     
     # Bind to events
     self.eventMouseDown.Bind(self._SliderOnDown)
     self.eventMouseUp.Bind(self._SliderOnUp)
     self.eventMotion.Bind(self._SliderOnMotion)
     self.eventPosition.Bind(self._SliderCalcDots)
Пример #3
0
 def _SliderOnDown(self, event):
     
     # Calc positions in normalized units
     x0 = self._getNormalizedCurrentPos(event)
     x1, x2 = self._getNormalizedSliderLimits()
     
     # Determine offset
     w,h = self.position.size
     offset = 8.0 / max(w,h)
     
     if x0 < x1+offset:
         # Move on left edge
         self._sliderDown = 1 
         self._sliderRefx = x1 - x0
     elif x0 > x2-offset:
         # Move on right edge
         self._sliderDown = 3
         self._sliderRefx = x2 - x0
     else:
         self._sliderDown = 2 # Move middle
         self._sliderRefx = (x1+x2)/2.0 - x0
     
     # Store original
     self._refRange = Range(self._range)
     
     # Update
     self.Draw()
Пример #4
0
    def GetLimits(self):
        """ GetLimits()
        
        Get the limits of the 2D axes as currently displayed. This can differ
        from what was set by SetLimits if the daspectAuto is False. 
        Returns a tuple of limits for x and y, respectively.
        
        Note: the limits are queried from the twod camera model, even 
        if this is not the currently used camera.
        
        """

        # get camera
        cam = self.camera
        if not isinstance(cam, cameras.TwoDCamera):
            cam = self._cameras['TwoDCamera']

        # Calculate viewing range for x and y
        fx = abs(1.0 / cam._zoom)
        fy = abs(1.0 / cam._zoom)
        # correct for window size
        w, h = self.position.size
        w, h = float(w), float(h)
        if w / h > 1:
            fx *= w / h
        else:
            fy *= h / w

        # calculate limits
        tmp = fx / 2 / self.daspectNormalized[0]
        xlim = Range(cam._view_loc[0] - tmp, cam._view_loc[0] + tmp)
        tmp = fy / 2 / self.daspectNormalized[1]
        ylim = Range(cam._view_loc[1] - tmp, cam._view_loc[1] + tmp)

        # return
        return xlim, ylim
Пример #5
0
    def SetLimits(self, rangeX=None, rangeY=None, rangeZ=None, margin=0.02):
        """ SetLimits(rangeX=None, rangeY=None, rangeZ=None, margin=0.02)
        
        Set the limits of the scene. For the 2D camera, these are taken 
        as hints to set the camera view. For the 3D camear, they determine
        where the axis is drawn.
        
        Returns a 3-element tuple of visvis.Range objects.
        
        Parameters
        ----------
        rangeX : (min, max), optional
            The range for the x dimension.
        rangeY : (min, max), optional
            The range for the y dimension.
        rangeZ : (min, max), optional
            The range for the z dimension.
        margin : scalar
            Represents the fraction of the range to add for the
            ranges that are automatically obtained (default 2%).
        
        Notes
        -----
        Each range can be None, a 2 element iterable, or a visvis.Range 
        object. If a range is None, the range is automatically obtained
        from the wobjects currently in the scene. To set the range that
        will fit all wobjects, simply use "SetLimits()"
        
        """

        # Check margin
        if margin and not isinstance(margin, float):
            raise ValueError('In SetLimits(): margin should be a float.')

        # if tuples, convert to ranges
        if rangeX is None or isinstance(rangeX, Range):
            pass  # ok
        elif hasattr(rangeX, '__len__') and len(rangeX) == 2:
            rangeX = Range(rangeX[0], rangeX[1])
        else:
            raise ValueError(
                "Limits should be Ranges or two-element iterables.")
        if rangeY is None or isinstance(rangeY, Range):
            pass  # ok
        elif hasattr(rangeY, '__len__') and len(rangeY) == 2:
            rangeY = Range(rangeY[0], rangeY[1])
        else:
            raise ValueError(
                "Limits should be Ranges or two-element iterables.")
        if rangeZ is None or isinstance(rangeZ, Range):
            pass  # ok
        elif hasattr(rangeZ, '__len__') and len(rangeZ) == 2:
            rangeZ = Range(rangeZ[0], rangeZ[1])
        else:
            raise ValueError(
                "Limits should be Ranges or two-element iterables.")

        rX, rY, rZ = rangeX, rangeY, rangeZ

        if None in [rX, rY, rZ]:

            # find outmost range
            wobjects = self.FindObjects(base.Wobject)
            for ob in wobjects:

                # Ask object what it's limits are
                tmp = ob._GetLimits()
                if not tmp:
                    continue
                tmpX, tmpY, tmpZ = tmp

                # Check for NaNs
                if tmpX.min * 0 != 0 or tmpX.max * 0 != 0:
                    tmpX = None
                if tmpY.min * 0 != 0 or tmpY.max * 0 != 0:
                    tmpY = None
                if tmpZ.min * 0 != 0 or tmpZ.max * 0 != 0:
                    tmpZ = None

                # update min/max
                if rangeX:
                    pass
                elif tmpX and rX:
                    rX = Range(min(rX.min, tmpX.min), max(rX.max, tmpX.max))
                elif tmpX:
                    rX = tmpX
                if rangeY:
                    pass
                elif tmpY and rY:
                    rY = Range(min(rY.min, tmpY.min), max(rY.max, tmpY.max))
                elif tmpY:
                    rY = tmpY
                if rangeZ:
                    pass
                elif tmpZ and rZ:
                    rZ = Range(min(rZ.min, tmpZ.min), max(rZ.max, tmpZ.max))
                elif tmpX:
                    rZ = tmpZ

        # default values
        if rX is None:
            rX = Range(-1, 1)
        if rY is None:
            rY = Range(0, 1)
        if rZ is None:
            rZ = Range(0, 1)

        # apply margins
        if margin:
            if rangeX is None:
                tmp = rX.range * margin
                if tmp == 0: tmp = margin
                rX = Range(rX.min - tmp, rX.max + tmp)
            if rangeY is None:
                tmp = rY.range * margin
                if tmp == 0: tmp = margin
                rY = Range(rY.min - tmp, rY.max + tmp)
            if rangeZ is None:
                tmp = rZ.range * margin
                if tmp == 0: tmp = margin
                rZ = Range(rZ.min - tmp, rZ.max + tmp)

        # apply to each camera
        for cam in self._cameras.values():
            cam.SetLimits(rX, rY, rZ)

        # return
        return rX, rY, rZ
Пример #6
0
 def _GetPolarLimits(self):
     if not self._points:
         return None
     else:
         return Range(self._angs.min(), self._angs.max()), \
                Range(self._mags.min(), self._mags.max())
Пример #7
0
 def fset(self, value):
     if not isinstance(value, Range):
         value = Range(value)
     self._SetClim(value)
Пример #8
0
 def __init__(self):
     self._colormap = Colormap()
     self._clim = Range(0, 1)
Пример #9
0
 def fset(self, value):
     self._range = Range(value)
     self._limitRangeAndSetText()
     #
     self._eventSliderChanged.Set()
     self._eventSliderChanged.Fire()
Пример #10
0
class BaseSlider(Box):
    """ BaseSlider(parent)
    
    Abstract slider class forming the base for the
    Slider and RangeSlider classes.
    
    """
    
    def __init__(self, parent):
        Box.__init__(self, parent)
        
        # init size
        self.position.w = 300
        self.position.h = 40
        
        # Slider specific stuff
        self._fullRange = Range(0,1)
        self._range = Range(0,1)
        self._refRange = Range(0,1) # For sliding
        self._showTicks = False
        
        # Set bgcolor and edge
        self.bgcolor = (0.6, 0.8, 0.6)
        self._frontColor = 0.5, 0.7, 0.9
        self.edgeWidth = 1
        
        # A slider should respond to mouse
        self.hitTest = True
        
        # Create label centered at the box
        self._label = Label(self)
        self._label.position = 0,0,1,1
        self._label.halign = 0
        self._label.bgcolor = None
        
        # State variables
        self._isOver = False
        self._sliderDown = False
        self._sliderRefx = 0.0
        
        # Pool of labels for tickmarks, to reuse them
        self._wobjects = [] # So we can have Text objects
        self._labelPool = {}
        
        # Calculate dots now
        self._SliderCalcDots()
        
        # Create new events
        self._eventSliding = BaseEvent(self)
        self._eventSliderChanged = BaseEvent(self)
        
        # To changes appearance on mouse over
        self.eventEnter.Bind(self._SliderOnEnter)
        self.eventLeave.Bind(self._SliderOnLeave)
        
        # Bind to events
        self.eventMouseDown.Bind(self._SliderOnDown)
        self.eventMouseUp.Bind(self._SliderOnUp)
        self.eventMotion.Bind(self._SliderOnMotion)
        self.eventPosition.Bind(self._SliderCalcDots)
    
    
    @property
    def eventSliding(self):
        """ Event fired when the user is sliding the slider. This can
        occur manu times during one sliding-opertaion.
        """
        return self._eventSliding
    
    
    @property    
    def eventSliderChanged(self):
        """ Event fired when the user releases the moude while changing
        the slider.
        """
        return self._eventSliderChanged
    
    
    @PropWithDraw
    def fullRange():
        """ The full possible range for this slider.
        """
        def fget(self):
            return self._fullRange
        def fset(self, value):
            self._fullRange = Range(value)
            self._limitRangeAndSetText()
        return locals()
    
    @PropWithDraw
    def showTicks():
        """ Whether to show tickmarks (default False).
        """
        def fget(self):
            return self._showTicks
        def fset(self, value):
            self._showTicks = bool(value)
        return locals()
    
    
    def _SliderOnEnter(self, event):
        self._isOver = True
        self.Draw()
    
    
    def _SliderOnLeave(self, event):
        self._isOver = False
        self.Draw()
    
    
    def _SliderOnDown(self, event):
        
        # Calc positions in normalized units
        x0 = self._getNormalizedCurrentPos(event)
        x1, x2 = self._getNormalizedSliderLimits()
        
        # Determine offset
        w,h = self.position.size
        offset = 8.0 / max(w,h)
        
        if x0 < x1+offset:
            # Move on left edge
            self._sliderDown = 1 
            self._sliderRefx = x1 - x0
        elif x0 > x2-offset:
            # Move on right edge
            self._sliderDown = 3
            self._sliderRefx = x2 - x0
        else:
            self._sliderDown = 2 # Move middle
            self._sliderRefx = (x1+x2)/2.0 - x0
        
        # Store original
        self._refRange = Range(self._range)
        
        # Update
        self.Draw()
    
    
    def _SliderOnMotion(self, event):
        
        if not self._sliderDown:
            return 
        
        # Calc current position in normalized units
        x0 = self._getNormalizedCurrentPos(event)
        
        # Reset before updating
        self._range = Range(self._refRange)
        
        # New normalized position
        dx =  x0 + self._sliderRefx
        offset = self._fullRange.min
        
        if self._sliderDown == 1:
            # Move on left edge
            self._range.min = self._fullRange.range * dx + offset
        elif self._sliderDown == 3:
            # Move on right edge
            self._range.max = self._fullRange.range * dx + offset
        elif self._sliderDown == 2:
            # Move whole slider
            ra2 = self._refRange.range / 2.0 
            mi = self._fullRange.range * dx - ra2 + offset
            ma = self._fullRange.range * dx + ra2 + offset
            self._range.Set(mi,ma)
        
        # Limit and update
        self._limitRangeAndSetText()
        self._eventSliding.Set()
        self._eventSliding.Fire()
        self.Draw()
    
    def _SliderOnUp(self, event):
        
        # Update values
        self._SliderOnMotion(event)
        
        # Release
        self._sliderDown = 0
        
        # Update
        self._eventSliderChanged.Set()
        self._eventSliderChanged.Fire()
    
    
    def _limitRangeAndSetText(self):
        """ _limitRangeAndSetText()
        To limit the range of the slider and to set the slider text.
        Different slider implementation want to do this
        differently.
        """
        pass # Abstact method
    
    
    def _getNormalizedCurrentPos(self, event):
        """ _getNormalizedCurrentPos(event)
        Get the current mouse position as a normalized range unit
        (between 0 and 1, with the fullRange as a references).
        """
        w,h = self.position.size
        if w > h:            
            return float(event.x) / self.position.width
        else:
            return float(event.y) / self.position.height
    
    
    def _getNormalizedSliderLimits(self):
        """ _getNormalizedSliderLimits()
        Get the current limits of the slider expressed in normalized 
        units (between 0 and 1, with the fullRange as a references).
        """
        # Short names
        R1 = self._range
        R2 = self._fullRange
        #
        factor = R2.range        
        x1 = (R1.min - R2.min) / factor
        x2 = x1 + R1.range / factor
        #
        return x1, x2
    
    
    def _GetBgcolorToDraw(self):
        """ Can be overloaded to indicate mouse over in buttons. 
        """
        clr = list(self._bgcolor)
        if self._isOver:
            clr = [c+0.05 for c in clr]
        return clr
    
    
    def _getformat(self):
        """ Get the format in which to display the slider limits. 
        """
        if self._fullRange.range > 10000:
            return '%1.4g'
        elif self._fullRange.range > 1000:
            return '%1.0f'
        elif self._fullRange.range > 100:
            return '%1.1f'
        elif self._fullRange.range > 10:
            return '%1.2f'
        else:
            return '%1.4g'
    
    
    def _SliderCalcDots(self, event=None):
        
        # Init dots
        dots1, dots2 = Pointset(2), Pointset(2)
        
        # Get width height
        w,h = self.position.size
        
        # Fill pointsets
        if w > h:
            i = 5
            while i < h-5:
                dots1.append(2,i); dots1.append(5,i)
                dots2.append(-2,i); dots2.append(-5,i)
                i += 3
        else:
            i = 5
            while i < w-5:
                dots1.append(i,2); dots1.append(i,5)
                dots2.append(i,-2); dots2.append(i,-5)
                i += 3
        
        self._dots1, self._dots2 = dots1, dots2
    
    
    def OnDraw(self):
        
        # Draw bg color and edges
        Box.OnDraw(self)
        
        # Margin
        d1 = 2
        d2 = d1+1
        
        # Get normalize limits        
        t1, t2 = self._getNormalizedSliderLimits()
        
        # Get widget shape
        w, h = self.position.size
        
        # Calculate real dimensions of patch
        if w > h:
            x1, x2 = max(d2, t1*w), min(w-d1, t2*w)            
            y1, y2 = d1, h-d2
            #
            dots1 = self._dots1 + Point(x1, 0)
            dots2 = self._dots2 + Point(x2, 0)
            #
            diff = abs(x1-x2)
            #
            self._label.textAngle = 0
        else:            
            x1, x2 = d2, w-d1
            y1, y2 = max(d1, t1*h), min(h-d2, t2*h)
            #
            dots1 = self._dots1 + Point(0, y1)
            dots2 = self._dots2 + Point(0, y2)
            #
            diff = abs(y1-y2)
            #
            self._label.textAngle = -90
        
        # Draw slider bit
        clr = self._frontColor
        gl.glColor(clr[0], clr[1], clr[2], 1.0)            
        #
        gl.glBegin(gl.GL_POLYGON)
        gl.glVertex2f(x1,y1)
        gl.glVertex2f(x1,y2)
        gl.glVertex2f(x2,y2)
        gl.glVertex2f(x2,y1)
        gl.glEnd()
        
        
        # Draw dots
        if True:
            
            # Prepare
            gl.glColor(0,0,0,1)
            gl.glPointSize(1)
            gl.glDisable(gl.GL_POINT_SMOOTH)
            
            # Draw
            gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
            if isinstance(self, RangeSlider) and diff>5:
                gl.glVertexPointerf(dots1.data)
                gl.glDrawArrays(gl.GL_POINTS, 0, len(dots1))
            if diff>5:
                gl.glVertexPointerf(dots2.data)
                gl.glDrawArrays(gl.GL_POINTS, 0, len(dots2))
            gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
        
        
        if self._showTicks:
            
            # Reset color to black
            gl.glColor(0,0,0,1)
            
            # Draw ticks
            if w>h:
                p0 = Point(0, h)
                p1 = Point(w, h)
                delta = Point(0,3)
                halign, valign = 0, 0
                xoffset, yoffset = -8, -2
            else:
                p0 = Point(w, h)
                p1 = Point(w, 0)
                delta = Point(3,0)
                halign, valign = -1, 0
                xoffset, yoffset = 5, -8
            
            # Get tickmarks
            ticks, ticksPos, ticksText = GetTicks(p0, p1, self._fullRange)
            
            newLabelPool = {}
            linePieces = Pointset(2)
            for tick, pos, text in zip(ticks, ticksPos, ticksText):
                pos2 = pos + delta
                
                # Add line piece
                linePieces.append(pos); linePieces.append(pos2)
                
                # Create or reuse label
                if tick in self._labelPool:
                    label = self._labelPool.pop(tick)
                else:
                    label = Label(self, ' '+text+' ')
                    label.bgcolor = ''
                
                # Position label and set text alignment
                newLabelPool[tick] = label
                label.halign, label.valign = halign, valign
                label.position.x = pos2.x + xoffset
                label.position.w = 16
                label.position.y = pos2.y + yoffset
            
            # Clean up label pool
            for label in self._labelPool.values():
                label.Destroy()
            self._labelPool = newLabelPool
            
            # Draw line pieces
            gl.glLineWidth(1)
            gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
            gl.glVertexPointerf(linePieces.data)
            gl.glDrawArrays(gl.GL_LINES, 0, len(linePieces))
            gl.glDisableClientState(gl.GL_VERTEX_ARRAY)
Пример #11
0
 def fset(self, value):
     self._fullRange = Range(value)
     self._limitRangeAndSetText()