dockart.py :  » Project-Management » Task-Coach » TaskCoach-1.0.3 » taskcoachlib » thirdparty » aui » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Project Management » Task Coach 
Task Coach » TaskCoach 1.0.3 » taskcoachlib » thirdparty » aui » dockart.py
"""
Dock art provider code - a dock provider provides all drawing functionality to
the AUI dock manager. This allows the dock manager to have a plugable look-and-feel.

By default, a L{AuiManager} uses an instance of this class called L{AuiDefaultDockArt}
which provides bitmap art and a colour scheme that is adapted to the major platforms'
look. You can either derive from that class to alter its behaviour or write a
completely new dock art class. Call L{AuiManager.SetArtProvider} to make use this
new dock art.
"""

__author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
__date__ = "31 March 2009"


import wx
import types

from aui_utilities import BitmapFromBits,StepColour,ChopText,GetBaseColour
from aui_utilities import DrawGradientRectangle,DrawMACCloseButton
from aui_utilities import DarkenBitmap,LightContrastColour
from aui_constants import *

optionActive = 2**14

_ctypes = False

# Try to import winxptheme for ModernDockArt
if wx.Platform == "__WXMSW__":
    try:
        import ctypes
        import winxptheme
        _ctypes = True
    except ImportError:
        pass

# -- AuiDefaultDockArt class implementation --

class AuiDefaultDockArt(object):
    """
    Dock art provider code - a dock provider provides all drawing functionality
    to the AUI dock manager. This allows the dock manager to have a plugable
    look-and-feel.

    By default, a L{AuiManager} uses an instance of this class called L{AuiDefaultDockArt}
    which provides bitmap art and a colour scheme that is adapted to the major
    platforms' look. You can either derive from that class to alter its behaviour or
    write a completely new dock art class.
    
    Call L{AuiManager.SetArtProvider} to make use this new dock art.


    **Metric Ordinals**

    These are the possible pane dock art settings for L{AuiManager}:

    ================================================  ======================================
    Metric Ordinal Constant                           Description
    ================================================  ======================================
    ``AUI_DOCKART_SASH_SIZE``                         Customizes the sash size
    ``AUI_DOCKART_CAPTION_SIZE``                      Customizes the caption size
    ``AUI_DOCKART_GRIPPER_SIZE``                      Customizes the gripper size
    ``AUI_DOCKART_PANE_BORDER_SIZE``                  Customizes the pane border size
    ``AUI_DOCKART_PANE_BUTTON_SIZE``                  Customizes the pane button size
    ``AUI_DOCKART_BACKGROUND_COLOUR``                 Customizes the background colour
    ``AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR``        Customizes the background gradient colour
    ``AUI_DOCKART_SASH_COLOUR``                       Customizes the sash colour
    ``AUI_DOCKART_ACTIVE_CAPTION_COLOUR``             Customizes the active caption colour
    ``AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR``    Customizes the active caption gradient colour
    ``AUI_DOCKART_INACTIVE_CAPTION_COLOUR``           Customizes the inactive caption colour
    ``AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR``  Customizes the inactive gradient caption colour
    ``AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR``        Customizes the active caption text colour
    ``AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR``      Customizes the inactive caption text colour
    ``AUI_DOCKART_BORDER_COLOUR``                     Customizes the border colour
    ``AUI_DOCKART_GRIPPER_COLOUR``                    Customizes the gripper colour
    ``AUI_DOCKART_CAPTION_FONT``                      Customizes the caption font
    ``AUI_DOCKART_GRADIENT_TYPE``                     Customizes the gradient type (no gradient, vertical or horizontal)
    ``AUI_DOCKART_DRAW_SASH_GRIP``                    Draw a sash grip on the sash
    ================================================  ======================================


    **Gradient Types**

    These are the possible gradient dock art settings for L{AuiManager}:

    ============================================  ======================================
    Gradient Constant                             Description 
    ============================================  ======================================
    ``AUI_GRADIENT_NONE``                         No gradient on the captions
    ``AUI_GRADIENT_VERTICAL``                     Vertical gradient on the captions
    ``AUI_GRADIENT_HORIZONTAL``                   Horizontal gradient on the captions
    ============================================  ======================================


    **Button States**

    These are the possible pane button / L{AuiNotebook} button / L{AuiToolBar} button states:

    ============================================  ======================================
    Button State Constant                         Description     
    ============================================  ======================================
    ``AUI_BUTTON_STATE_NORMAL``                   Normal button state
    ``AUI_BUTTON_STATE_HOVER``                    Hovered button state
    ``AUI_BUTTON_STATE_PRESSED``                  Pressed button state
    ``AUI_BUTTON_STATE_DISABLED``                 Disabled button state
    ``AUI_BUTTON_STATE_HIDDEN``                   Hidden button state
    ``AUI_BUTTON_STATE_CHECKED``                  Checked button state
    ============================================  ======================================


    **Button Identifiers**

    These are the possible pane button / L{AuiNotebook} button / L{AuiToolBar} button identifiers:

    ============================================  ======================================
    Button Identifier                             Description     
    ============================================  ======================================
    ``AUI_BUTTON_CLOSE``                          Shows a close button on the pane
    ``AUI_BUTTON_MAXIMIZE_RESTORE``               Shows a maximize/restore button on the pane
    ``AUI_BUTTON_MINIMIZE``                       Shows a minimize button on the pane
    ``AUI_BUTTON_PIN``                            Shows a pin button on the pane
    ``AUI_BUTTON_OPTIONS``                        Shows an option button on the pane (not implemented)
    ``AUI_BUTTON_WINDOWLIST``                     Shows a window list button on the pane (for AuiNotebook)
    ``AUI_BUTTON_LEFT``                           Shows a left button on the pane (for AuiNotebook)
    ``AUI_BUTTON_RIGHT``                          Shows a right button on the pane (for AuiNotebook)
    ``AUI_BUTTON_UP``                             Shows an up button on the pane (not implemented)
    ``AUI_BUTTON_DOWN``                           Shows a down button on the pane (not implemented)
    ``AUI_BUTTON_CUSTOM1``                        Shows a custom button on the pane (not implemented)
    ``AUI_BUTTON_CUSTOM2``                        Shows a custom button on the pane (not implemented)
    ``AUI_BUTTON_CUSTOM3``                        Shows a custom button on the pane (not implemented)
    ============================================  ======================================
    
    """

    def __init__(self):
        """ Default class constructor. """

        self.Init()

        isMac = wx.Platform == "__WXMAC__"
        
        if isMac:
            self._caption_font = wx.SMALL_FONT
        else:
            self._caption_font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)

        self.SetDefaultPaneBitmaps(isMac)
        self._restore_bitmap = wx.BitmapFromXPMData(restore_xpm)
        
        # default metric values
        self._sash_size = 4

        if isMac:
            # This really should be implemented in wx.SystemSettings
            # There is no way to do this that I am aware outside of using
            # the cocoa python bindings. 8 pixels looks correct on my system
            # so hard coding it for now.

            # How do I translate this?!? Not sure of the below implementation...
            # SInt32 height;
            # GetThemeMetric( kThemeMetricSmallPaneSplitterHeight , &height );
            # self._sash_size = height;

            self._sash_size = 8 # Carbon.Appearance.kThemeMetricPaneSplitterHeight            
            
        elif wx.Platform == "__WXGTK__":
            self._sash_size = wx.RendererNative.Get().GetSplitterParams(wx.GetTopLevelWindows()[0]).widthSash

        else:
            self._sash_size = 4
        
        self._caption_size = 19
        self._border_size = 1
        self._button_size = 14
        self._gripper_size = 9
        self._gradient_type = AUI_GRADIENT_VERTICAL
        self._draw_sash = False
        

    def Init(self):
        """ Initializes the dock art. """

        base_colour = GetBaseColour()
        darker1_colour = StepColour(base_colour, 85)
        darker2_colour = StepColour(base_colour, 75)
        darker3_colour = StepColour(base_colour, 60)
        darker4_colour = StepColour(base_colour, 40)

        self._background_colour = base_colour
        self._background_gradient_colour = StepColour(base_colour, 180)

        isMac = wx.Platform == "__WXMAC__"

        if isMac:
            self._active_caption_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
        else:
            self._active_caption_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION)

        self._active_caption_gradient_colour = LightContrastColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT))
        self._active_caption_text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
        self._inactive_caption_colour = darker1_colour
        self._inactive_caption_gradient_colour = StepColour(base_colour, 97)
        self._inactive_caption_text_colour = wx.BLACK
    
        self._sash_brush = wx.Brush(base_colour)
        self._background_brush = wx.Brush(base_colour)
        self._border_pen = wx.Pen(darker2_colour)
        self._gripper_brush = wx.Brush(base_colour)
        self._gripper_pen1 = wx.Pen(darker4_colour)
        self._gripper_pen2 = wx.Pen(darker3_colour)
        self._gripper_pen3 = wx.WHITE_PEN

        
    def GetMetric(self, id):
        """
        Gets the value of a certain setting.

        :param `id`: can be one of the size values in `Metric Ordinals`.
        """


        if id == AUI_DOCKART_SASH_SIZE:
            return self._sash_size
        elif id == AUI_DOCKART_CAPTION_SIZE:
            return self._caption_size
        elif id == AUI_DOCKART_GRIPPER_SIZE:
            return self._gripper_size
        elif id == AUI_DOCKART_PANE_BORDER_SIZE:
            return self._border_size
        elif id == AUI_DOCKART_PANE_BUTTON_SIZE:
            return self._button_size
        elif id == AUI_DOCKART_GRADIENT_TYPE:
            return self._gradient_type
        elif id == AUI_DOCKART_DRAW_SASH_GRIP:
            return self._draw_sash
        else:
            raise Exception("Invalid Metric Ordinal.")


    def SetMetric(self, id, new_val):
        """
        Sets the value of a certain setting using `new_val`

        :param `id`: can be one of the size values in `Metric Ordinals`;
        :param `new_val`: the new value of the setting.
        """

        if id == AUI_DOCKART_SASH_SIZE:
            self._sash_size = new_val
        elif id == AUI_DOCKART_CAPTION_SIZE:
            self._caption_size = new_val
        elif id == AUI_DOCKART_GRIPPER_SIZE:
            self._gripper_size = new_val
        elif id == AUI_DOCKART_PANE_BORDER_SIZE:
            self._border_size = new_val
        elif id == AUI_DOCKART_PANE_BUTTON_SIZE:
            self._button_size = new_val
        elif id == AUI_DOCKART_GRADIENT_TYPE:
            self._gradient_type = new_val
        elif id == AUI_DOCKART_DRAW_SASH_GRIP:
            self._draw_sash = new_val
        else:
            raise Exception("Invalid Metric Ordinal.")


    def GetColor(self, id):
        """
        Gets the colour of a certain setting.

        :param `id`: can be one of the colour values in `Metric Ordinals`.
        """

        if id == AUI_DOCKART_BACKGROUND_COLOUR:
            return self._background_brush.GetColour()
        elif id == AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR:
            return self._background_gradient_colour
        elif id == AUI_DOCKART_SASH_COLOUR:
            return self._sash_brush.GetColour()
        elif id == AUI_DOCKART_INACTIVE_CAPTION_COLOUR:
            return self._inactive_caption_colour
        elif id == AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR:
            return self._inactive_caption_gradient_colour
        elif id == AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR:
            return self._inactive_caption_text_colour
        elif id == AUI_DOCKART_ACTIVE_CAPTION_COLOUR:
            return self._active_caption_colour
        elif id == AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR:
            return self._active_caption_gradient_colour
        elif id == AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR:
            return self._active_caption_text_colour        
        elif id == AUI_DOCKART_BORDER_COLOUR:
            return self._border_pen.GetColour()
        elif id == AUI_DOCKART_GRIPPER_COLOUR:
            return self._gripper_brush.GetColour()
        else:
            raise Exception("Invalid Colour Ordinal.")


    def SetColor(self, id, colour):
        """
        Sets the colour of a certain setting.

        :param `id`: can be one of the colour values in `Metric Ordinals`;
        :param `colour`: the new value of the setting.
        """

        if isinstance(colour, basestring):
            colour = wx.NamedColour(colour)
        elif isinstance(colour, types.TupleType):
            colour = wx.Colour(*colour)
        elif isinstance(colour, types.IntType):
            colour = wx.ColourRGB(colour)
        
        if id == AUI_DOCKART_BACKGROUND_COLOUR:
            self._background_brush.SetColour(colour)
        elif id == AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR:
            self._background_gradient_colour = colour
        elif id == AUI_DOCKART_SASH_COLOUR:
            self._sash_brush.SetColour(colour)
        elif id == AUI_DOCKART_INACTIVE_CAPTION_COLOUR:
            self._inactive_caption_colour = colour
            if not self._custom_pane_bitmaps and wx.Platform == "__WXMAC__":
                # No custom bitmaps for the pane close button
                # Change the MAC close bitmap colour
                self._inactive_close_bitmap = DrawMACCloseButton(wx.WHITE, colour)

        elif id == AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR:
            self._inactive_caption_gradient_colour = colour
        elif id == AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR:
            self._inactive_caption_text_colour = colour
        elif id == AUI_DOCKART_ACTIVE_CAPTION_COLOUR:
            self._active_caption_colour = colour
            if not self._custom_pane_bitmaps and wx.Platform == "__WXMAC__":
                # No custom bitmaps for the pane close button
                # Change the MAC close bitmap colour
                self._active_close_bitmap = DrawMACCloseButton(wx.WHITE, colour)
                
        elif id == AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR:
            self._active_caption_gradient_colour = colour
        elif id == AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR:
            self._active_caption_text_colour = colour
        elif id == AUI_DOCKART_BORDER_COLOUR:
            self._border_pen.SetColour(colour)
        elif id == AUI_DOCKART_GRIPPER_COLOUR:
            self._gripper_brush.SetColour(colour)
            self._gripper_pen1.SetColour(StepColour(colour, 40))
            self._gripper_pen2.SetColour(StepColour(colour, 60))
        else:
            raise Exception("Invalid Colour Ordinal.")
        

    GetColour = GetColor
    SetColour = SetColor

    def SetFont(self, id, font):
        """
        Sets a font setting.
        
        :param `id`: must be ``AUI_DOCKART_CAPTION_FONT``;
        :param `font`: an instance of `wx.Font`.
        """
        
        if id == AUI_DOCKART_CAPTION_FONT:
            self._caption_font = font


    def GetFont(self, id):
        """
        Gets a font setting.
        
        :param `id`: must be ``AUI_DOCKART_CAPTION_FONT``, otherwise `wx.NullFont` is returned.
        """
        
        if id == AUI_DOCKART_CAPTION_FONT:
            return self._caption_font
        
        return wx.NullFont


    def DrawSash(self, dc, window, orient, rect):
        """
        Draws a sash between two windows.

        :param `dc`: a `wx.DC` device context;
        :param `window`: an instance of `wx.Window`;
        :param `orient`: the sash orientation;
        :param `rect`: the sash rectangle.
        """                

        # AG: How do we make this work?!?
        # RendererNative does not use the sash_brush chosen by the user
        # and the rect.GetSize() is ignored as the sash is always drawn
        # 3 pixel wide
        # wx.RendererNative.Get().DrawSplitterSash(window, dc, rect.GetSize(), pos, orient)

        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.SetBrush(self._sash_brush)
        dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)        

        draw_sash = self.GetMetric(AUI_DOCKART_DRAW_SASH_GRIP)
        if draw_sash:
            self.DrawSashGripper(dc, orient, rect)


    def DrawBackground(self, dc, window, orient, rect):
        """
        Draws a background.

        :param `dc`: a `wx.DC` device context;
        :param `window`: an instance of `wx.Window`;
        :param `orient`: the gradient (if any) orientation;
        :param `rect`: the background rectangle.
        """

        dc.SetPen(wx.TRANSPARENT_PEN)
        if wx.Platform == "__WXMAC__":
            # we have to clear first, otherwise we are drawing a light striped pattern
            # over an already darker striped background
            dc.SetBrush(wx.WHITE_BRUSH)
            dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)

        DrawGradientRectangle(dc, rect, self._background_colour,
                              self._background_gradient_colour,
                              AUI_GRADIENT_HORIZONTAL, rect.x, 700)


    def DrawBorder(self, dc, window, rect, pane):
        """
        Draws the pane border.

        :param `dc`: a `wx.DC` device context;
        :param `window`: an instance of `wx.Window`;
        :param `rect`: the border rectangle;
        :param `pane`: the pane for which the border is drawn.
        """        

        drect = wx.Rect(*rect)
        
        dc.SetPen(self._border_pen)
        dc.SetBrush(wx.TRANSPARENT_BRUSH)

        border_width = self.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)

        if pane.IsToolbar():
        
            for ii in xrange(0, border_width):
            
                dc.SetPen(wx.WHITE_PEN)
                dc.DrawLine(drect.x, drect.y, drect.x+drect.width, drect.y)
                dc.DrawLine(drect.x, drect.y, drect.x, drect.y+drect.height)
                dc.SetPen(self._border_pen)       
                dc.DrawLine(drect.x, drect.y+drect.height-1,
                            drect.x+drect.width, drect.y+drect.height-1)
                dc.DrawLine(drect.x+drect.width-1, drect.y,
                            drect.x+drect.width-1, drect.y+drect.height)
                drect.Deflate(1, 1)
        
        else:
        
            for ii in xrange(0, border_width):
            
                dc.DrawRectangle(drect.x, drect.y, drect.width, drect.height)
                drect.Deflate(1, 1)
            

    def DrawCaptionBackground(self, dc, rect, pane):
        """
        Draws the text caption background in the pane.

        :param `dc`: a `wx.DC` device context;
        :param `rect`: the text caption rectangle;
        :param `pane`: the pane for which the text background is drawn.
        """        

        active = pane.state & optionActive
 
        if self._gradient_type == AUI_GRADIENT_NONE:
            if active:
                dc.SetBrush(wx.Brush(self._active_caption_colour))
            else:
                dc.SetBrush(wx.Brush(self._inactive_caption_colour))

            dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)        

        else:

            switch_gradient = pane.HasCaptionLeft()
            gradient_type = self._gradient_type
            if switch_gradient:
                gradient_type = (self._gradient_type == AUI_GRADIENT_HORIZONTAL and [AUI_GRADIENT_VERTICAL] or \
                                 [AUI_GRADIENT_HORIZONTAL])[0]
            
            if active:
                if wx.Platform == "__WXMAC__":
                    DrawGradientRectangle(dc, rect, self._active_caption_colour,
                                          self._active_caption_gradient_colour,
                                          gradient_type)                    
                else:
                    DrawGradientRectangle(dc, rect, self._active_caption_gradient_colour,
                                          self._active_caption_colour,
                                          gradient_type)
            else:
                if wx.Platform == "__WXMAC__":
                    DrawGradientRectangle(dc, rect, self._inactive_caption_gradient_colour,
                                          self._inactive_caption_colour,
                                          gradient_type)
                else:
                    DrawGradientRectangle(dc, rect, self._inactive_caption_colour,
                                          self._inactive_caption_gradient_colour,
                                          gradient_type)


    def DrawIcon(self, dc, rect, pane):
        """
        Draws the icon in the pane caption area.

        :param `dc`: a `wx.DC` device context;
        :param `rect`: the pane caption rectangle;
        :param `pane`: the pane for which the icon is drawn.
        """        
        
        # Draw the icon centered vertically 
        if pane.icon.Ok():
            if pane.HasCaptionLeft():
                bmp = wx.ImageFromBitmap(pane.icon).Rotate90(clockwise=False)
                dc.DrawBitmap(bmp.ConvertToBitmap(), rect.x+(rect.width-pane.icon.GetWidth())/2, rect.y+rect.height-2-pane.icon.GetHeight(), True)
            else:
                dc.DrawBitmap(pane.icon, rect.x+2, rect.y+(rect.height-pane.icon.GetHeight())/2, True)


    def DrawCaption(self, dc, window, text, rect, pane):
        """
        Draws the text in the pane caption.

        :param `dc`: a `wx.DC` device context;
        :param `window`: an instance of `wx.Window`;
        :param `text`: the text to be displayed;
        :param `rect`: the pane caption rectangle;
        :param `pane`: the pane for which the text is drawn.
        """        

        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.SetFont(self._caption_font)
        
        self.DrawCaptionBackground(dc, rect, pane)

        if pane.state & optionActive:
            dc.SetTextForeground(self._active_caption_text_colour)
        else:
            dc.SetTextForeground(self._inactive_caption_text_colour)

        w, h = dc.GetTextExtent("ABCDEFHXfgkj")

        clip_rect = wx.Rect(*rect)
        btns = pane.CountButtons()

        captionLeft = pane.HasCaptionLeft()
        variable = (captionLeft and [rect.height] or [rect.width])[0]

        variable -= 3      # text offset
        variable -= 2      # button padding

        caption_offset = 0
        if pane.icon:
            if captionLeft:
                caption_offset += pane.icon.GetHeight() + 3
            else:
                caption_offset += pane.icon.GetWidth() + 3
                
            self.DrawIcon(dc, rect, pane)

        variable -= caption_offset
        variable -= btns*(self._button_size + self._border_size)
        draw_text = ChopText(dc, text, variable)

        if captionLeft:
            dc.DrawRotatedText(draw_text, rect.x+(rect.width/2)-(h/2)-1, rect.y+rect.height-3-caption_offset, 90)
        else:
            dc.DrawText(draw_text, rect.x+3+caption_offset, rect.y+(rect.height/2)-(h/2)-1)


    def RequestUserAttention(self, dc, window, text, rect, pane):
        """
        Requests the user attention by intermittently highlighting the pane caption.

        :param `dc`: a `wx.DC` device context;
        :param `window`: an instance of `wx.Window`;
        :param `text`: the text to be displayed;
        :param `rect`: the pane caption rectangle;
        :param `pane`: the pane for which the text is drawn.
        """        

        state = pane.state
        pane.state &= ~optionActive
        
        for indx in xrange(6):
            active = (indx%2 == 0 and [True] or [False])[0]
            if active:
                pane.state |= optionActive
            else:
                pane.state &= ~optionActive
                
            self.DrawCaptionBackground(dc, rect, pane)
            self.DrawCaption(dc, window, text, rect, pane)
            wx.SafeYield()
            wx.MilliSleep(350)

        pane.state = state
        

    def DrawGripper(self, dc, window, rect, pane):
        """
        Draws a gripper on the pane.

        :param `dc`: a `wx.DC` device context;
        :param `window`: an instance of `wx.Window`;
        :param `rect`: the pane caption rectangle;
        :param `pane`: the pane for which the gripper is drawn.
        """        

        dc.SetPen(wx.TRANSPARENT_PEN)
        dc.SetBrush(self._gripper_brush)

        dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)

        if not pane.HasGripperTop():
            y = 4
            while 1:
                dc.SetPen(self._gripper_pen1)
                dc.DrawPoint(rect.x+3, rect.y+y) 
                dc.SetPen(self._gripper_pen2) 
                dc.DrawPoint(rect.x+3, rect.y+y+1) 
                dc.DrawPoint(rect.x+4, rect.y+y) 
                dc.SetPen(self._gripper_pen3) 
                dc.DrawPoint(rect.x+5, rect.y+y+1) 
                dc.DrawPoint(rect.x+5, rect.y+y+2) 
                dc.DrawPoint(rect.x+4, rect.y+y+2) 
                y = y + 4 
                if y > rect.GetHeight() - 4:
                    break
        else:
            x = 4
            while 1:
                dc.SetPen(self._gripper_pen1) 
                dc.DrawPoint(rect.x+x, rect.y+3) 
                dc.SetPen(self._gripper_pen2) 
                dc.DrawPoint(rect.x+x+1, rect.y+3) 
                dc.DrawPoint(rect.x+x, rect.y+4) 
                dc.SetPen(self._gripper_pen3) 
                dc.DrawPoint(rect.x+x+1, rect.y+5) 
                dc.DrawPoint(rect.x+x+2, rect.y+5) 
                dc.DrawPoint(rect.x+x+2, rect.y+4) 
                x = x + 4 
                if x > rect.GetWidth() - 4:
                    break 
        

    def DrawPaneButton(self, dc, window, button, button_state, _rect, pane):
        """
        Draws a pane button in the pane caption area.

        :param `dc`: a `wx.DC` device context;
        :param `window`: an instance of `wx.Window`;
        :param `button`: the button to be drawn;
        :param `button_state`: the pane button state;
        :param `_rect`: the pane caption rectangle;
        :param `pane`: the pane for which the button is drawn.
        """        
        
        if not pane:
            return
        
        if button == AUI_BUTTON_CLOSE:
            if pane.state & optionActive:
                bmp = self._active_close_bitmap
            else:
                bmp = self._inactive_close_bitmap

        elif button == AUI_BUTTON_PIN:
            if pane.state & optionActive:
                bmp = self._active_pin_bitmap
            else:
                bmp = self._inactive_pin_bitmap

        elif button == AUI_BUTTON_MAXIMIZE_RESTORE:
            if pane.IsMaximized():
                if pane.state & optionActive:
                    bmp = self._active_restore_bitmap
                else:
                    bmp = self._inactive_restore_bitmap
            else:
                if pane.state & optionActive:
                    bmp = self._active_maximize_bitmap
                else:
                    bmp = self._inactive_maximize_bitmap

        elif button == AUI_BUTTON_MINIMIZE:
            if pane.state & optionActive:
                bmp = self._active_minimize_bitmap
            else:
                bmp = self._inactive_minimize_bitmap

        isVertical = pane.HasCaptionLeft()
        
        rect = wx.Rect(*_rect)

        if isVertical:
            old_x = rect.x
            rect.x = rect.x + (rect.width/2) - (bmp.GetWidth()/2)
            rect.width = old_x + rect.width - rect.x - 1
        else:
            old_y = rect.y
            rect.y = rect.y + (rect.height/2) - (bmp.GetHeight()/2)
            rect.height = old_y + rect.height - rect.y - 1

        if button_state == AUI_BUTTON_STATE_PRESSED:
            rect.x += 1
            rect.y += 1

        if button_state in [AUI_BUTTON_STATE_HOVER, AUI_BUTTON_STATE_PRESSED]:

            if pane.state & optionActive:

                dc.SetBrush(wx.Brush(StepColour(self._active_caption_colour, 120)))
                dc.SetPen(wx.Pen(StepColour(self._active_caption_colour, 70)))

            else:

                dc.SetBrush(wx.Brush(StepColour(self._inactive_caption_colour, 120)))
                dc.SetPen(wx.Pen(StepColour(self._inactive_caption_colour, 70)))

            if wx.Platform != "__WXMAC__":
                # draw the background behind the button
                dc.DrawRectangle(rect.x, rect.y, 15, 15)
            else:
                # Darker the bitmap a bit
                bmp = DarkenBitmap(bmp, self._active_caption_colour, StepColour(self._active_caption_colour, 110))

        if isVertical:
            bmp = wx.ImageFromBitmap(bmp).Rotate90(clockwise=False).ConvertToBitmap()
            
        # draw the button itself
        dc.DrawBitmap(bmp, rect.x, rect.y, True)


    def DrawSashGripper(self, dc, orient, rect):
        """
        Draws a sash gripper on a sash between two windows.

        :param `dc`: a `wx.DC` device context;
        :param `orient`: the sash orientation;
        :param `rect`: the sash rectangle.
        """
        
        dc.SetBrush(self._gripper_brush)

        if orient == wx.HORIZONTAL:  # horizontal sash
            
            x = rect.x + int((1.0/4.0)*rect.width)
            xend = rect.x + int((3.0/4.0)*rect.width)
            y = rect.y + (rect.height/2) - 1

            while 1:
                dc.SetPen(self._gripper_pen3)
                dc.DrawRectangle(x, y, 2, 2)
                dc.SetPen(self._gripper_pen2) 
                dc.DrawPoint(x+1, y+1)
                x = x + 5

                if x >= xend:
                    break

        else:

            y = rect.y + int((1.0/4.0)*rect.height)
            yend = rect.y + int((3.0/4.0)*rect.height)
            x = rect.x + (rect.width/2) - 1

            while 1:
                dc.SetPen(self._gripper_pen3)
                dc.DrawRectangle(x, y, 2, 2)
                dc.SetPen(self._gripper_pen2) 
                dc.DrawPoint(x+1, y+1)
                y = y + 5

                if y >= yend:
                    break


    def SetDefaultPaneBitmaps(self, isMac):
        """
        Assigns the default pane bitmaps.

        :param `isMac`: whether we are on wxMAC or not.
        """

        if isMac:
            self._inactive_close_bitmap = DrawMACCloseButton(wx.WHITE, self._inactive_caption_colour)
            self._active_close_bitmap = DrawMACCloseButton(wx.WHITE, self._active_caption_colour)
        else:
            self._inactive_close_bitmap = BitmapFromBits(close_bits, 16, 16, self._inactive_caption_text_colour)
            self._active_close_bitmap = BitmapFromBits(close_bits, 16, 16, self._active_caption_text_colour)
            
        if isMac:
            self._inactive_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, wx.WHITE)
            self._active_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, wx.WHITE)
        else:
            self._inactive_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, self._inactive_caption_text_colour)
            self._active_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, self._active_caption_text_colour)

        if isMac:
            self._inactive_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, wx.WHITE)
            self._active_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, wx.WHITE)
        else:
            self._inactive_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, self._inactive_caption_text_colour)
            self._active_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, self._active_caption_text_colour)

        if isMac:
            self._inactive_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, wx.WHITE)
            self._active_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, wx.WHITE)
        else:
            self._inactive_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, self._inactive_caption_text_colour)
            self._active_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, self._active_caption_text_colour)

        self._inactive_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, self._inactive_caption_text_colour)
        self._active_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, self._active_caption_text_colour)

        self._custom_pane_bitmaps = False
        
        
    def SetCustomPaneBitmap(self, bmp, button, active, maximize=False):
        """
        Sets a custom button bitmap for the pane button.

        :param `bmp`: the actual bitmap to set;
        :param `button`: the button identifier;
        :param `active`: whether it is the bitmap for the active button or not;
        :param `maximize`: used to distinguish between the maximize and restore bitmaps.
        """

        if bmp.GetWidth() > 16 or bmp.GetHeight() > 16:
            raise Exception("The input bitmap is too big")

        if button == AUI_BUTTON_CLOSE:
            if active:
                self._active_close_bitmap = bmp
            else:
                self._inactive_close_bitmap = bmp

            if wx.Platform == "__WXMAC__":
                self._custom_pane_bitmaps = True                

        elif button == AUI_BUTTON_PIN:
            if active:
                self._active_pin_bitmap = bmp
            else:
                self._inactive_pin_bitmap = bmp

        elif button == AUI_BUTTON_MAXIMIZE_RESTORE:
            if maximize:
                if active:
                    self._active_maximize_bitmap = bmp
                else:
                    self._inactive_maximize_bitmap = bmp
            else:
                if active:
                    self._active_restore_bitmap = bmp
                else:
                    self._inactive_restore_bitmap = bmp

        elif button == AUI_BUTTON_MINIMIZE:
            if active:
                self._active_minimize_bitmap = bmp
            else:
                self._inactive_minimize_bitmap = bmp


if _ctypes:
    class RECT(ctypes.Structure):
        """ Used to handle L{ModernDockArt} on Windows XP/Vista/7. """
        _fields_ = [('left', ctypes.c_ulong),('top', ctypes.c_ulong),('right', ctypes.c_ulong),('bottom', ctypes.c_ulong)]

        def dump(self):
            """ Dumps `self` as a `wx.Rect`. """
            return map(int, (self.left, self.top, self.right, self.bottom))


    class SIZE(ctypes.Structure):
        """ Used to handle L{ModernDockArt} on Windows XP/Vista/7. """
        _fields_ = [('x', ctypes.c_long),('y', ctypes.c_long)]


class ModernDockArt(AuiDefaultDockArt):
    """
    ModernDockArt is a custom `AuiDockArt` class, that implements a look similar to
    Firefox and other recents applications. 

    Is uses the `winxptheme` module and XP themes whenever possible, so it should
    look good even if the user has a custom theme.
    """

    def __init__(self, win):
        """
        Default class constructor. 

        :param `win`: the window managed by L{AuiManager}. 
        """
        
        AuiDefaultDockArt.__init__(self)
        
        self.win = win

        # Get the size of a small close button (themed)
        hwnd = self.win.GetHandle()
        
        self.hTheme1 = winxptheme.OpenThemeData(hwnd, "Window")
        
        self.usingTheme = True
        
        if not self.hTheme1:
            self.usingTheme = False

        self._button_size = 13

        self._button_border_size = 3
        self._caption_text_indent = 6
        self._caption_size = 22
        
        # We only highlight the active pane with the caption text being in bold.
        # So we do not want a special colour for active elements.        
        self._active_close_bitmap = self._inactive_close_bitmap

        self.Init()
        

    def Init(self):
        """ Initializes the dock art. """

        AuiDefaultDockArt.Init(self)
        
        self._active_caption_colour = self._inactive_caption_colour
        self._active_caption_text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_CAPTIONTEXT)
        self._inactive_caption_text_colour = self._active_caption_text_colour


    def DrawCaption(self, dc, window, text, rect, pane):
        """
        Draws the text in the pane caption.

        :param `dc`: a `wx.DC` device context;
        :param `window`: an instance of `wx.Window`;
        :param `text`: the text to be displayed;
        :param `rect`: the pane caption rectangle;
        :param `pane`: the pane for which the text is drawn.
        """        

        dc.SetPen(wx.TRANSPARENT_PEN)
        self.DrawCaptionBackground(dc, rect, pane)

        active = ((pane.state & optionActive) and [True] or [False])[0]

        self._caption_font.SetWeight(wx.FONTWEIGHT_BOLD)
        dc.SetFont(self._caption_font)
        
        if active:
            dc.SetTextForeground(self._active_caption_text_colour)
        else:
            dc.SetTextForeground(self._inactive_caption_text_colour)

        w, h = dc.GetTextExtent("ABCDEFHXfgkj")

        clip_rect = wx.Rect(*rect)
        btns = pane.CountButtons()

        captionLeft = pane.HasCaptionLeft()
        variable = (captionLeft and [rect.height] or [rect.width])[0]

        variable -= 3      # text offset
        variable -= 2      # button padding

        caption_offset = 0
        if pane.icon:
            if captionLeft:
                caption_offset += pane.icon.GetHeight() + 3
            else:
                caption_offset += pane.icon.GetWidth() + 3
                
            self.DrawIcon(dc, rect, pane)

        diff = -2
        if self.usingTheme:
            diff = -1

        variable -= caption_offset
        variable -= btns*(self._button_size + self._button_border_size)
        draw_text = ChopText(dc, text, variable)

        if captionLeft:
            dc.DrawRotatedText(draw_text, rect.x+(rect.width/2)-(h/2)-diff, rect.y+rect.height-3-caption_offset, 90)
        else:
            dc.DrawText(draw_text, rect.x+3+caption_offset, rect.y+(rect.height/2)-(h/2)-diff)


    def DrawCaptionBackground(self, dc, rect, pane):
        """
        Draws the text caption background in the pane.

        :param `dc`: a `wx.DC` device context;
        :param `rect`: the text caption rectangle;
        :param `pane`: the pane for which we are drawing the caption background.
        """        

        dc.SetBrush(self._background_brush)
        dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)

        active = ((pane.state & optionActive) and [True] or [False])[0]

        if self.usingTheme:
            
            rectangle = wx.Rect()

            rc = RECT(rectangle.x, rectangle.y, rectangle.width, rectangle.height)

            rc.top = rect.x
            rc.left = rect.y
            rc.right = rect.x + rect.width
            rc.bottom = rect.y + rect.height

            if active:
                winxptheme.DrawThemeBackground(self.hTheme1, dc.GetHDC(), 5, 1, (rc.top, rc.left, rc.right, rc.bottom), None)
            else:
                winxptheme.DrawThemeBackground(self.hTheme1, dc.GetHDC(), 5, 2, (rc.top, rc.left, rc.right, rc.bottom), None)
            
        else:

            AuiDefaultDockArt.DrawCaptionBackground(self, dc, rect, pane)


    def RequestUserAttention(self, dc, window, text, rect, pane):
        """
        Requests the user attention by intermittently highlighting the pane caption.

        :param `dc`: a `wx.DC` device context;
        :param `window`: an instance of `wx.Window`;
        :param `text`: the text to be displayed;
        :param `rect`: the pane caption rectangle;
        :param `pane`: the pane for which the text is drawn.
        """        
    
        state = pane.state
        pane.state &= ~optionActive
        
        for indx in xrange(6):
            active = (indx%2 == 0 and [True] or [False])[0]
            if active:
                pane.state |= optionActive
            else:
                pane.state &= ~optionActive
                
            self.DrawCaptionBackground(dc, rect, pane)
            self.DrawCaption(dc, window, text, rect, pane)
            wx.SafeYield()
            wx.MilliSleep(350)

        pane.state = state


    def DrawPaneButton(self, dc, window, button, button_state, rect, pane):
        """
        Draws a pane button in the pane caption area.

        :param `dc`: a `wx.DC` device context;
        :param `window`: an instance of `wx.Window`;
        :param `button`: the button to be drawn;
        :param `button_state`: the pane button state;
        :param `rect`: the pane caption rectangle;
        :param `pane`: the pane for which the button is drawn.
        """        

        if self.usingTheme:

            hTheme = self.hTheme1            
                    
            # Get the real button position (compensating for borders)
            drect = wx.Rect(rect.x, rect.y, self._button_size, self._button_size)
            
            # Draw the themed close button
            rc = RECT(0, 0, 0, 0)
            if pane.HasCaptionLeft():
                rc.top = rect.x + self._button_border_size
                rc.left = int(rect.y + 1.5*self._button_border_size)
                rc.right = rect.x + self._button_size + self._button_border_size
                rc.bottom = int(rect.y + self._button_size + 1.5*self._button_border_size)
            else:
                rc.top = rect.x - self._button_border_size
                rc.left = int(rect.y + 1.5*self._button_border_size)
                rc.right = rect.x + self._button_size- self._button_border_size
                rc.bottom = int(rect.y + self._button_size + 1.5*self._button_border_size)

            if button == AUI_BUTTON_CLOSE:
                btntype = 19
                
            elif button == AUI_BUTTON_PIN:
                btntype = 23

            elif button == AUI_BUTTON_MAXIMIZE_RESTORE:
                if not pane.IsMaximized():
                    btntype = 17
                else:
                    btntype = 21
            else:
                btntype = 15

            state = 4 # CBS_DISABLED
            
            if pane.state & optionActive:

                if button_state == AUI_BUTTON_STATE_NORMAL:
                    state = 1 # CBS_NORMAL

                elif button_state == AUI_BUTTON_STATE_HOVER:
                    state = 2 # CBS_HOT

                elif button_state == AUI_BUTTON_STATE_PRESSED:
                    state = 3 # CBS_PUSHED

                else:
                    raise Exception("ERROR: Unknown State.")

            else: # inactive pane

                if button_state == AUI_BUTTON_STATE_NORMAL:
                    state = 5 # CBS_NORMAL

                elif button_state == AUI_BUTTON_STATE_HOVER:
                    state = 6 # CBS_HOT

                elif button_state == AUI_BUTTON_STATE_PRESSED:
                    state = 7 # CBS_PUSHED

                else:
                    raise Exception("ERROR: Unknown State.")

            try:
                winxptheme.DrawThemeBackground(hTheme, dc.GetHDC(), btntype, state, (rc.top, rc.left, rc.right, rc.bottom), None)
            except TypeError:
                return

        else:

            # Fallback to default closebutton if themes are not enabled
            rect2 = wx.Rect(rect.x-4, rect.y+2, rect.width, rect.height)
            AuiDefaultDockArt.DrawPaneButton(self, dc, window, button, button_state, rect2, pane)

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.