dabo Commit
Revision 2252
Date: 2006-07-13 09:41:37 -0700 (Thu, 13 Jul 2006)
Author: ed

Changed:
U   trunk/dabo/ui/uiwx/__init__.py
U   trunk/dabo/ui/uiwx/dKeys.py
U   trunk/dabo/ui/uiwx/dPemMixin.py
U   trunk/dabo/ui/uiwx/dSplitter.py

Log:
Added the drawGradient() method. This will draw a gradient that varies between 
the two colors specified in either the horizontal or vertical direction, 
depending on the orientation of the gradient.

There are still some problems with getting the drawing to stay 'behind' the 
other elements, which are sometimes drawn before the gradient, but perhaps some 
enterprising soul will figure out how to deal with this. The code to draw the 
gradients is taken from Andrea Gavana's FoldPanelBar class, where he uses it to 
draw the gradients on the caption bars.


Diff:
Modified: trunk/dabo/ui/uiwx/__init__.py
===================================================================
--- trunk/dabo/ui/uiwx/__init__.py      2006-07-13 03:10:20 UTC (rev 2251)
+++ trunk/dabo/ui/uiwx/__init__.py      2006-07-13 16:41:37 UTC (rev 2252)
@@ -291,7 +291,7 @@
        
        if isinstance(wxEvt, (wx.KeyEvent, wx.MouseEvent, wx.TreeEvent,
                        wx.CommandEvent, wx.CloseEvent, wx.grid.GridEvent,
-                       wx.grid.GridSizeEvent) ):
+                       wx.grid.GridSizeEvent, wx.SplitterEvent) ):
                
                if dabo.allNativeEventInfo:
                        # Cycle through all the attributes of the wx events, 
and evaluate them
@@ -313,6 +313,12 @@
                        except:
                                pass
                
+       if isinstance(wxEvt, (wx.SplitterEvent,) ):
+               try:
+                       ed["mousePosition"] = (wxEvt.GetX(), wxEvt.GetY())
+               except:
+                       ed["mousePosition"] = wx.GetMousePosition()
+
        if isinstance(wxEvt, (wx.KeyEvent, wx.MouseEvent) ):
                ed["mousePosition"] = wxEvt.GetPositionTuple()
                ed["altDown"] = wxEvt.AltDown()
@@ -382,6 +388,15 @@
                except:
                        pass
        
+       if isinstance(wxEvt, wx.SplitterEvent):
+               if hasattr(wxEvt, "GetSashPosition"):
+                       ed["sashPosition"] = wxEvt.GetSashPosition()
+               if hasattr(wxEvt, "GetWindowBeingRemoved"):
+                       try:
+                               ed["windowRemoved"] = 
wxEvt.GetWindowBeingRemoved()
+                       except:
+                               ed["windowRemoved"] = None
+               
        if hasattr(wxEvt, "GetId"):
                ed["id"] = wxEvt.GetId()
 

Modified: trunk/dabo/ui/uiwx/dKeys.py
===================================================================
--- trunk/dabo/ui/uiwx/dKeys.py 2006-07-13 03:10:20 UTC (rev 2251)
+++ trunk/dabo/ui/uiwx/dKeys.py 2006-07-13 16:41:37 UTC (rev 2252)
@@ -174,4 +174,41 @@
        "f12": key_F12,
        "numlock": key_Numlock,
        "scroll": key_Scroll,
+       "numpad_0": key_Numpad0, 
+       "numpad_1": key_Numpad1, 
+       "numpad_2": key_Numpad2, 
+       "numpad_3": key_Numpad3, 
+       "numpad_4": key_Numpad4, 
+       "numpad_5": key_Numpad5, 
+       "numpad_6": key_Numpad6, 
+       "numpad_7": key_Numpad7, 
+       "numpad_8": key_Numpad8, 
+       "numpad_9": key_Numpad9, 
+       "numpad_space": key_Numpad_space, 
+       "numpad_tab": key_Numpad_tab, 
+       "numpad_enter": key_Numpad_enter, 
+       "numpad_f1": key_Numpad_f1, 
+       "numpad_f2": key_Numpad_f2, 
+       "numpad_f3": key_Numpad_f3, 
+       "numpad_f4": key_Numpad_f4, 
+       "numpad_home": key_Numpad_home, 
+       "numpad_left": key_Numpad_left, 
+       "numpad_up": key_Numpad_up, 
+       "numpad_right": key_Numpad_right, 
+       "numpad_down": key_Numpad_down, 
+       "numpad_prior": key_Numpad_prior, 
+       "numpad_pageup": key_Numpad_pageup, 
+       "numpad_next": key_Numpad_next, 
+       "numpad_pagedown": key_Numpad_pagedown, 
+       "numpad_end": key_Numpad_end, 
+       "numpad_begin": key_Numpad_begin, 
+       "numpad_insert": key_Numpad_insert, 
+       "numpad_delete": key_Numpad_delete, 
+       "numpad_equal": key_Numpad_equal, 
+       "numpad_multiply": key_Numpad_multiply, 
+       "numpad_add": key_Numpad_add, 
+       "numpad_separator": key_Numpad_separator, 
+       "numpad_subtract": key_Numpad_subtract, 
+       "numpad_decimal": key_Numpad_decimal, 
+       "numpad_divide": key_Numpad_divide, 
 }

Modified: trunk/dabo/ui/uiwx/dPemMixin.py
===================================================================
--- trunk/dabo/ui/uiwx/dPemMixin.py     2006-07-13 03:10:20 UTC (rev 2251)
+++ trunk/dabo/ui/uiwx/dPemMixin.py     2006-07-13 16:41:37 UTC (rev 2252)
@@ -237,7 +237,7 @@
        def _preInitUI(self, kwargs):
                """Subclass hook, for internal Dabo use. 
 
-               Some wx objects (RadioBox) need certain props forced if they 
hadn't been 
+               Some wx objects (RadioBox) need certain props forced if they 
hadn't been 
                set by the user either as a parm or in beforeInit().
                """
                return kwargs
@@ -670,7 +670,7 @@
                This can significantly improve performance when many items are 
being 
                updated at once.
 
-               IMPORTANT: you must call unlockDisplay() when you are done,     
or your 
+               IMPORTANT: you must call unlockDisplay() when you are done, or 
your 
                object will never draw.
 
                Note that lockDisplay currently doesn't do anything on GTK.
@@ -685,8 +685,8 @@
                that would result in lengthy screen updates.
                """
                self.Thaw()
-       
-       
+
+
        def addObject(self, classRef, Name=None, *args, **kwargs):
                """ Instantiate object as a child of self.
                
@@ -808,7 +808,7 @@
        def getPositionInSizer(self):
                """ Returns the current position of this control in its 
containing sizer. 
 
-               This is useful for when a control needs to be re-created in     
place. If the 
+               This is useful for when a control needs to be re-created in 
place. If the 
                containing sizer is a box sizer, the integer position will be 
returned. 
                If it is a grid sizer, a row,col tuple will be returned. If the 
object is 
                not contained in a sizer, None will be returned.
@@ -845,8 +845,8 @@
                If 'recurse' is True, setAll() will be called on each child as 
well.
 
                If 'filt' is not empty, only children that match the expression 
in 'filt' 
-               will be affected. The expression will be evaluated assuming     
the child 
-               object is prefixed to the expression. For example, if   you 
want to only 
+               will be affected. The expression will be evaluated assuming the 
child 
+               object is prefixed to the expression. For example, if you want 
to only 
                affect objects that are instances of dButton, you'd call:
 
                form.setAll("FontBold", True, filt="BaseClass == 
dabo.ui.dButton")
@@ -931,7 +931,7 @@
 
 
        def __onUpdate(self, evt):
-               """Update any dynamic properties, and then call the refresh() 
hook."""
+               """Update any dynamic properties, and then call the refresh() 
hook."""
                if isinstance(self, dabo.ui.deadObject):
                        return
                self.update()
@@ -1133,9 +1133,23 @@
                # Add it to the list of drawing objects
                obj = self._addToDrawnObjects(obj, persist)
                return obj
+       
+       
+       def drawGradient(self, orientation, x=0, y=0, width=None, height=None,
+                       color1=None, color2=None, persist=True):
+               """Draws a horizontal or vertical gradient on the control. 
Default
+               is to cover the entire control, although you can specify 
positions.
+               The gradient is drawn with 'color1' as the top/left color, and 
'color2'
+               as the bottom/right color.
+               """
+               obj = DrawObject(self, Shape="gradient", 
Orientation=orientation, 
+                               Xpos=x, Ypos=y, Width=width, Height=height,
+                               GradientColor1=color1, GradientColor2=color2)
+               # Add it to the list of drawing objects
+               obj = self._addToDrawnObjects(obj, persist)
+               return obj
                
                
-               
        def _addToDrawnObjects(self, obj, persist):
                self._drawnObjects.append(obj)
                self._redraw()
@@ -2011,7 +2025,7 @@
                        
                        This property is write-only at runtime.""") )
                
-       Parent = property(_getParent, _setParent, None, 
+       Parent = property(_getParent, _setParent, None, 
                        _("The containing object. (obj)") )
 
        Position = property(_getPosition, _setPosition, None, 
@@ -2039,8 +2053,8 @@
                        _("The top position of the object. (int)") )
        
        Visible = property(_getVisible, _setVisible, None,
-                       _("Specifies whether the object is visible at runtime. 
(bool)") )                    
-
+                       _("Specifies whether the object is visible at runtime.  
(bool)") )
+       
        Width = property(_getWidth, _setWidth, None,
                        _("The width of the object. (int)") )
        
@@ -2109,6 +2123,9 @@
                self._backColor = None
                self._text = None
                self._angle = 0
+               self._gradientColor1 = None
+               self._gradientColor2 = None
+               self._orientation = None
                self._transparent = True
                super(DrawObject, self).__init__(*args, **kwargs)
                self._inInit = False
@@ -2176,6 +2193,8 @@
                        x1, y1 = self.Points[0]
                        x2, y2 = self.Points[1]
                        dc.DrawLine(x1, y1, x2, y2)
+               elif self.Shape == "gradient":
+                       self._drawGradient(dc)
                elif self.Shape == "text":
                        txt = self._text
                        if not txt:
@@ -2209,6 +2228,63 @@
                                dc.DrawRotatedText(txt, self.Xpos, self.Ypos, 
self._angle)
                                        
        
+       def _drawGradient(self, dc):
+               if self.GradientColor1 is None or self.GradientColor2 is None:
+                       return
+               if self.Orientation is None:
+                       return
+               if self.Width is None:
+                       wd = self.Parent.Width
+               else:
+                       wd = self.Width
+               if self.Xpos is None:
+                       x1 = 0
+                       x2 = wd
+               else:
+                       x1 = self.Xpos
+                       x2 = x1 + wd
+               if self.Height is None:
+                       ht = self.Parent.Height
+               else:
+                       ht = self.Height
+               if self.Ypos is None:
+                       y1 = 0
+                       y2 = ht
+               else:
+                       y1 = self.Ypos
+                       y2 = y1 + ht
+                       
+               dc.SetPen(wx.TRANSPARENT_PEN)
+               r1, g1, b1 = self.GradientColor1
+               r2, g2, b2 = self.GradientColor2
+
+               if self.Orientation == "h":
+                       flrect = float(wd)
+               else:
+                       flrect = float(ht)
+               rstep = float((r2 - r1)) / flrect
+               gstep = float((g2 - g1)) / flrect
+               bstep = float((b2 - b1)) / flrect
+
+               rf, gf, bf = 0, 0, 0
+               if self.Orientation == "h":
+                       for x in range(x1, x1 + wd):
+                               currRow = (r1 + rf, g1 + gf, b1 + bf)           
                        
+                               dc.SetBrush(wx.Brush(currRow, wx.SOLID))
+                               dc.DrawRectangle(x1 + (x - x1), y1, 1, ht)
+                               rf = rf + rstep
+                               gf = gf + gstep
+                               bf = bf + bstep
+               else:
+                       for y in range(y1, y1 + ht):
+                               currCol = (r1 + rf, g1 + gf, b1 + bf)
+                               dc.SetBrush(wx.Brush(currCol, wx.SOLID))
+                               dc.DrawRectangle(x1, y1 + (y - y1), wd, ht)
+                               rf = rf + rstep
+                               gf = gf + gstep
+                               bf = bf + bstep
+
+
        def bringToFront(self):
                self.Parent._bringDrawObjectToFront(self)
                
@@ -2316,6 +2392,28 @@
                        self.update()
 
 
+       def _getGradientColor1(self):
+               return self._gradientColor1
+
+       def _setGradientColor1(self, val):
+               if isinstance(val, basestring):
+                       val = dColors.colorTupleFromName(val)
+               if self._gradientColor1 != val:
+                       self._gradientColor1 = val
+                       self.update()
+
+
+       def _getGradientColor2(self):
+               return self._gradientColor2
+
+       def _setGradientColor2(self, val):
+               if isinstance(val, basestring):
+                       val = dColors.colorTupleFromName(val)
+               if self._gradientColor2 != val:
+                       self._gradientColor2 = val
+                       self.update()
+
+
        def _getHeight(self):
                return self._height
                
@@ -2336,6 +2434,16 @@
                        self.update()
                        
 
+       def _getOrientation(self):
+               return self._orientation
+
+       def _setOrientation(self, val):
+               val = val[0].lower()
+               if self._orientation != val:
+                       self._orientation = val
+                       self.update()
+
+
        def _getParent(self):
                return self._parent
                
@@ -2451,9 +2559,6 @@
        FontBold = property(_getFontBold, _setFontBold, None,
                        _("Bold setting for text objects  (bool)"))
        
-       ForeColor = property(_getForeColor, _setForeColor, None,
-                       _("Color of text when using text objects  (str or 
tuple)"))
-       
        FontFace = property(_getFontFace, _setFontFace, None,
                        _("Face of the font used for text objects  (str)"))
        
@@ -2466,11 +2571,23 @@
        FontUnderline = property(_getFontUnderline, _setFontUnderline, None,
                        _("Underline setting for text objects  (bool)"))
        
+       ForeColor = property(_getForeColor, _setForeColor, None,
+                       _("Color of text when using text objects  (str or 
tuple)"))
+       
+       GradientColor1 = property(_getGradientColor1, _setGradientColor1, None,
+                       _("Top/Left color for the gradient  (color: str or 
tuple)"))
+       
+       GradientColor2 = property(_getGradientColor2, _setGradientColor2, None,
+                       _("Bottom/Right color for the gradient  (color: str or 
tuple)"))
+       
        Height = property(_getHeight, _setHeight, None,
                        _("For rectangles, the height of the shape  (int)"))
 
        LineStyle = property(_getLineStyle, _setLineStyle, None,
                        _("Line style (solid, dash, dot) drawn  (str)"))
+       
+       Orientation = property(_getOrientation, _setOrientation, None,
+                       _("Direction of the drawn gradient ('v' or 'h')  
(str)"))
 
        Parent = property(_getParent, _setParent, None,
                        _("Reference to the object being drawn upon.  
(object)"))

Modified: trunk/dabo/ui/uiwx/dSplitter.py
===================================================================
--- trunk/dabo/ui/uiwx/dSplitter.py     2006-07-13 03:10:20 UTC (rev 2251)
+++ trunk/dabo/ui/uiwx/dSplitter.py     2006-07-13 16:41:37 UTC (rev 2252)
@@ -10,15 +10,13 @@
 from dabo.ui import makeDynamicProperty
 
 
-class SplitterPanel(dabo.ui.dPanel):
-       def __init__(self, parent):
-               self._showSplitMenu = True
-               super(SplitterPanel, self).__init__(parent)
+class SplitterPanelMixin:
+       def __init__(self, *args, **kwargs):
                if self.ShowSplitMenu:
-                       self.bindEvent(dEvents.ContextMenu, self._onContextMenu)
+                       self.bindEvent(dEvents.ContextMenu, 
self._onMixinContextMenu)
        
        
-       def _onContextMenu(self, evt):
+       def _onMixinContextMenu(self, evt):
                evt.stop()
                sm = dabo.ui.dMenu(self)
                sm.append("Split this pane", bindfunc=self.onSplit)
@@ -76,7 +74,11 @@
        
        # Property definitions start here
        def _getShowSplitMenu(self):
-               return self._showSplitMenu
+               try:
+                       ret = self._showSplitMenu
+               except AttributeError:
+                       ret = self._showSplitMenu = True
+               return ret
 
        def _setShowSplitMenu(self, val):
                if self._constructed():
@@ -97,7 +99,7 @@
                
 class dSplitter(wx.SplitterWindow, cm.dControlMixin):
        """ Main class for handling split windows. It will contain two
-       panels (subclass of SplitterPanel), each of which can further 
+       panels (subclass of SplitterPanelMixin), each of which can further 
        split itself in two.
        """
        def __init__(self, parent, properties=None, *args, **kwargs):
@@ -106,13 +108,16 @@
                style = self._extractKey((kwargs, properties), "style", 0)
                self._createPanes = self._extractKey((kwargs, properties), 
"createPanes", False)
                self._splitOnInit = self._extractKey((kwargs, properties), 
"splitOnInit", True)
+               self._p1 = self._p2 = None
+               # Default to a decent minimum panel size if none is specified
+               mp = self._extractKey((kwargs, properties), "MinimumPanelSize", 
20)
+               kwargs["MinimumPanelSize"] = mp
                        
                # Default to vertical split
                self._orientation = "v"
                self._sashPos = 100
-               self._minPanelSize = 0
                # Default to showing the context menus on the panels
-               self._showPanelSplitMenu = None
+               self._showPanelSplitMenu = True
 
                preClass = wx.PreSplitterWindow
                cm.dControlMixin.__init__(self, preClass, parent, properties, 
@@ -126,8 +131,8 @@
 
 
        def _afterInit(self):
-               self.__p1 = None
-               self.__p2 = None
+               self._p1 = None
+               self._p2 = None
                # Create the panes
                if self._createPanes:
                        self.createPanes()
@@ -135,10 +140,33 @@
                        self.split()
                super(dSplitter, self)._afterInit()
 
-                       
-       def createPanes(self):
-               self.__p1 = self.PanelClass(self)
-               self.__p2 = self.PanelClass(self)
+       
+       def _makeSplitterPanelClass(self, cls):
+               # See if the class already is mixed in with the 
SplitterPanelMixin
+               if isinstance(cls, SplitterPanelMixin):
+                       ret = cls
+               else:
+                       class MixedSplitterPanel(cls, SplitterPanelMixin):
+                               def __init__(self, parent, *args, **kwargs):
+                                       cls.__init__(self, parent, *args, 
**kwargs)
+                                       SplitterPanelMixin.__init__(self, 
*args, **kwargs)
+                       ret = MixedSplitterPanel
+               return ret
+
+
+       def createPanes(self, cls=None, pane=None):
+               if cls is None:
+                       cls = self.PanelClass
+               spCls = self._makeSplitterPanelClass(cls)
+               if pane is None:
+                       p1 = p2 = True
+               else:
+                       p1 = (pane == 1)
+                       p2 = (pane == 2)
+               if p1 and self.Panel1 is None:
+                       self.Panel1 = spCls(self)
+               if p2 and self.Panel2 is None:
+                       self.Panel2 = spCls(self)
                if self.IsSplit():
                        self.unsplit()
                        self.split()
@@ -165,6 +193,7 @@
                
        def _onSashPos(self, evt):
                """Fires when the sash position is changed."""
+               evt.Skip()
                # Update the internal sash position attribute.
                self._getSashPosition()
                # Raise a dEvent for other code to bind to,
@@ -175,8 +204,8 @@
                if self.IsSplit():
                        return
                if self.Panel1 is None or self.Panel2 is None:
-                       # No panels, so we can't split
-                       return
+                       # No panels, so we can't split! Create them.
+                       self.createPanes()
                        
                if dir_:
                        self.Orientation = dir_
@@ -216,9 +245,9 @@
                if self.IsSplit():
                        self.unsplit(pnl)
                else:
-                       # If the parent of this is a SplitterPanel, tell it to 
hide
+                       # If the parent of this is a SplitterPanelMixin, tell 
it to hide
                        prnt = self.Parent
-                       if isinstance(prnt, SplitterPanel):
+                       if isinstance(prnt, SplitterPanelMixin):
                                prnt.remove()
                        else:
                                self.Destroy()                          
@@ -252,12 +281,17 @@
                if self._constructed():
                        orient = val.lower()[0]
                        if orient in ("h", "v"):
-                               self._orientation = orient
+                               self._orientation = {"h": "Horizontal", "v": 
"Vertical"}[orient]
                                if self.IsSplit():
                                        self.lockDisplay()
                                        self.unsplit()
                                        self.split()
                                        self.unlockDisplay()
+                               else:
+                                       self.lockDisplay()
+                                       self.split()
+                                       self.unsplit()
+                                       self.unlockDisplay()
                        else:
                                raise ValueError, "Orientation can only be 
'Horizontal' or 'Vertical'"
                else:
@@ -265,16 +299,17 @@
        
        
        def _getPanel1(self):
-               return self.__p1
+               return self._p1
                
        def _setPanel1(self, pnl):
                if self._constructed():
                        splt = self.IsSplit()
                        if splt:
-                               self.unsplit(self.__p1)
-                       if self.__p1:
-                               self.__p1.Destroy()
-                       self.__p1 = pnl
+                               self.unsplit(self._p1)
+                       if self._p1:
+                               self.ReplaceWindow(self._p1, pnl)
+                               self._p1.Destroy()
+                       self._p1 = pnl
                        if splt:
                                self.split()
                else:
@@ -282,16 +317,18 @@
                        
 
        def _getPanel2(self):
-               return self.__p2
+               return self._p2
                
        def _setPanel2(self, pnl):
                if self._constructed():
                        splt = self.IsSplit()
                        if splt:
-                               self.unsplit(self.__p2)
-                       if self.__p2:
-                               self.__p2.Destroy()
-                       self.__p2 = pnl
+                               self.unsplit(self._p2)
+                       if self._p2:
+                               self.split()
+                               self.ReplaceWindow(self._p2, pnl)
+                               self._p2.Destroy()
+                       self._p2 = pnl
                        if splt:
                                self.split()
                else:
@@ -302,7 +339,7 @@
                try:
                        ret = self._panelClass
                except:
-                       ret = self._panelClass = SplitterPanel
+                       ret = self._panelClass = dabo.ui.dPanel
                return ret
                
        def _setPanelClass(self, val):
@@ -358,9 +395,11 @@
                        _("Returns the Bottom/Right panel.  (dPanel)"))
 
        PanelClass = property(_getPanelClass, _setPanelClass, None,
-                       _("""Class used for creating panels. This must be set 
before the panels are
-                       created; setting it afterward has no effect unless you 
destroy the panels
-                       and re-create them.  Default=SplitterPanel  
(dPanel)"""))
+                       _("""Class used for creating panels. If the class does 
not descend from 
+                       SplitterPanelMixin, that class will be mixed-into the 
class specified here. 
+                       This must be set before the panels are created; setting 
it afterward has 
+                       no effect unless you destroy the panels and re-create 
them.  
+                       Default=dPanel  (dPanel)"""))
                        
        SashPosition = property(_getSashPosition, _setSashPosition, None,
                        _("Position of the sash when the window is split.  
(int)"))




_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev

Reply via email to