aui_utilities.py :  » GUI » wxPython » wxPython-src-2.8.11.0 » wxPython » wx » lib » agw » 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 » GUI » wxPython 
wxPython » wxPython src 2.8.11.0 » wxPython » wx » lib » agw » aui » aui_utilities.py
"""
This module contains some common functions used by wxPython-AUI to
manipulate colours, bitmaps, text, gradient shadings and custom
dragging images for AuiNotebook tabs.
"""

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


import wx

from aui_constants import *


if wx.Platform == "__WXMAC__":
    import Carbon.Appearance
    
    
def BlendColour(fg, bg, alpha):
    """
    Blends the two colour component `fg` and `bg` into one colour component, adding
    an optional alpha channel.

    :param `fg`: the first colour component;
    :param `bg`: the second colour component;
    :param `alpha`: an optional transparency value.
    """
    
    result = bg + (alpha*(fg - bg))
    
    if result < 0.0:
        result = 0.0
    if result > 255:
        result = 255
        
    return result


def StepColour(c, ialpha):
    """
    Darken/lighten the input colour `c`.

    :param `c`: a colour to darken/lighten;
    :param `ialpha`: a transparency value.
    """
    
    if ialpha == 100:
        return c
        
    r, g, b = c.Red(), c.Green(), c.Blue()

    # ialpha is 0..200 where 0 is completely black
    # and 200 is completely white and 100 is the same
    # convert that to normal alpha 0.0 - 1.0
    ialpha = min(ialpha, 200)
    ialpha = max(ialpha, 0)
    alpha = (ialpha - 100.0)/100.0

    if ialpha > 100:
    
        # blend with white
        bg = 255
        alpha = 1.0 - alpha  # 0 = transparent fg 1 = opaque fg
    
    else:
    
        # blend with black
        bg = 0
        alpha = 1.0 + alpha  # 0 = transparent fg 1 = opaque fg
    
    r = BlendColour(r, bg, alpha)
    g = BlendColour(g, bg, alpha)
    b = BlendColour(b, bg, alpha)

    return wx.Colour(r, g, b)


def LightContrastColour(c):
    """
    Creates a new, lighter colour based on the input colour `c`.

    :param `c`: the input colour to analyze.
    """

    amount = 120

    # if the colour is especially dark, then
    # make the contrast even lighter
    if c.Red() < 128 and c.Green() < 128 and c.Blue() < 128:
        amount = 160

    return StepColour(c, amount)


def ChopText(dc, text, max_size):
    """
    Chops the input `text` if its size does not fit in `max_size`, by cutting the
    text and adding ellipsis at the end.

    :param `dc`: a `wx.DC` device context;
    :param `text`: the text to chop;
    :param `max_size`: the maximum size in which the text should fit.
    """
    
    # first check if the text fits with no problems
    x, y, dummy = dc.GetMultiLineTextExtent(text)
    
    if x <= max_size:
        return text

    textLen = len(text)
    last_good_length = 0
    
    for i in xrange(textLen, -1, -1):
        s = text[0:i]
        s += "..."

        x, y = dc.GetTextExtent(s)
        last_good_length = i
        
        if x < max_size:
            break

    ret = text[0:last_good_length] + "..."    
    return ret


def BitmapFromBits(bits, w, h, colour):
    """
    BitmapFromBits() is a utility function that creates a
    masked bitmap from raw bits (XBM format).

    :param `bits`: a string containing the raw bits of the bitmap;
    :param `w`: the bitmap width;
    :param `h`: the bitmap height;
    :param `colour`: the colour which will replace all white pixels in the
     raw bitmap.
    """

    img = wx.BitmapFromBits(bits, w, h).ConvertToImage()
    img.Replace(0, 0, 0, 123, 123, 123)
    img.Replace(255, 255, 255, colour.Red(), colour.Green(), colour.Blue())
    img.SetMaskColour(123, 123, 123)
    return wx.BitmapFromImage(img)


def IndentPressedBitmap(rect, button_state):
    """
    Indents the input rectangle `rect` based on the value of `button_state`.

    :param `rect`: an instance of wx.Rect;
    :param `button_state`: an L{AuiNotebook} button state.
    """

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

    return rect


def GetBaseColour():
    """
    Returns the face shading colour on push buttons/backgrounds, mimicking as closely
    as possible the platform UI colours.
    """

    if wx.Platform == "__WXMAC__":

        if hasattr(wx, 'MacThemeColour'):
            base_colour = wx.MacThemeColour(Carbon.Appearance.kThemeBrushToolbarBackground)
        else:
            brush = wx.Brush(wx.BLACK)
            brush.MacSetTheme(Carbon.Appearance.kThemeBrushToolbarBackground)
            base_colour = brush.GetColour()

    else:
        
        base_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE)

    # the base_colour is too pale to use as our base colour,
    # so darken it a bit
    if ((255-base_colour.Red()) +
        (255-base_colour.Green()) +
        (255-base_colour.Blue()) < 60):
    
        base_colour = StepColour(base_colour, 92)
    
    return base_colour


def MakeDisabledBitmap(bitmap):
    """
    Convert the given image (in place) to a grayed-out version,
    appropriate for a 'disabled' appearance.

    :param `bitmap`: the bitmap to gray-out.
    """

    anImage = bitmap.ConvertToImage()    
    factor = 0.7        # 0 < f < 1.  Higher Is Grayer
    
    if anImage.HasMask():
        maskColour = (anImage.GetMaskRed(), anImage.GetMaskGreen(), anImage.GetMaskBlue())
    else:
        maskColour = None
        
    data = map(ord, list(anImage.GetData()))

    for i in range(0, len(data), 3):
        
        pixel = (data[i], data[i+1], data[i+2])
        pixel = MakeGray(pixel, factor, maskColour)

        for x in range(3):
            data[i+x] = pixel[x]

    anImage.SetData(''.join(map(chr, data)))
    
    return anImage.ConvertToBitmap()


def MakeGray(rgbTuple, factor, maskColour):
    """
    Make a pixel grayed-out. If the pixel matches the `maskColour`, it won't be
    changed.

    :param `rgbTuple`: a tuple representing a pixel colour;
    :param `factor`: a graying-out factor;
    :param `maskColour`: a colour mask.
    """

    if rgbTuple != maskColour:
        r, g, b = rgbTuple
        return map(lambda x: int((230 - x) * factor) + x, (r, g, b))
    else:
        return rgbTuple


def Clip(a, b, c):
    """
    Clips the value in `a` based on the extremes `b` and `c`.

    :param `a`: the value to analyze;
    :param `b`: a minimum value;
    :param `c`: a maximum value.
    """

    return ((a < b and [b]) or [(a > c and [c] or [a])[0]])[0]


def LightColour(colour, percent):
    """
    Brighten input `colour` by `percent`.

    :param `colour`: the colour to be brightened;
    :param `percent`: brightening percentage.
    """
    
    end_colour = wx.WHITE
    
    rd = end_colour.Red() - colour.Red()
    gd = end_colour.Green() - colour.Green()
    bd = end_colour.Blue() - colour.Blue()

    high = 100

    # We take the percent way of the colour from colour -. white
    i = percent
    r = colour.Red() + ((i*rd*100)/high)/100
    g = colour.Green() + ((i*gd*100)/high)/100
    b = colour.Blue() + ((i*bd*100)/high)/100
    return wx.Colour(r, g, b)


def PaneCreateStippleBitmap():
    """
    Creates a stipple bitmap to be used in a `wx.Brush`.
    This is used to draw sash resize hints.
    """

    data = [0, 0, 0, 192, 192, 192, 192, 192, 192, 0, 0, 0]
    img = wx.EmptyImage(2, 2)
    counter = 0
    
    for ii in xrange(2):
        for jj in xrange(2):
            img.SetRGB(ii, jj, data[counter], data[counter+1], data[counter+2])
            counter = counter + 3
    
    return img.ConvertToBitmap()


def DrawMACCloseButton(colour, backColour=None):
    """
    Draws the wxMAC tab close button using `wx.GraphicsContext`.

    :param `colour`: the colour to use to draw the circle;
    :param `backColour`: the optional background colour for the circle.
    """

    bmp = wx.EmptyBitmapRGBA(16, 16)
    dc = wx.MemoryDC()
    dc.SelectObject(bmp)

    gc = wx.GraphicsContext.Create(dc)    
    gc.SetBrush(wx.Brush(colour))
    path = gc.CreatePath()
    path.AddCircle(6.5, 7, 6.5)
    path.CloseSubpath()
    gc.FillPath(path)
    
    path = gc.CreatePath()
    if backColour is not None:
        pen = wx.Pen(backColour, 2)
    else:
        pen = wx.Pen("white", 2)
        
    pen.SetCap(wx.CAP_BUTT)
    pen.SetJoin(wx.JOIN_BEVEL)
    gc.SetPen(pen)
    path.MoveToPoint(3.5, 4)
    path.AddLineToPoint(9.5, 10)
    path.MoveToPoint(3.5, 10)
    path.AddLineToPoint(9.5, 4)
    path.CloseSubpath()
    gc.DrawPath(path)

    dc.SelectObject(wx.NullBitmap)
    return bmp


def DarkenBitmap(bmp, caption_colour, new_colour):
    """
    Darkens the input bitmap on wxMAC using the input colour.
    
    :param `bmp`: the bitmap to be manipulated;
    :param `caption_colour`: the colour of the pane caption;
    :param `new_colour`: the colour used to darken the bitmap.
    """

    image = bmp.ConvertToImage()
    red = caption_colour.Red()/float(new_colour.Red())
    green = caption_colour.Green()/float(new_colour.Green())
    blue = caption_colour.Blue()/float(new_colour.Blue())
    image = image.AdjustChannels(red, green, blue)
    return image.ConvertToBitmap()

    
def DrawGradientRectangle(dc, rect, start_colour, end_colour, direction, offset=0, length=0):
    """
    Draws a gradient-shaded rectangle.

    :param `dc`: a `wx.DC` device context;
    :param `rect`: the rectangle in which to draw the gradient;
    :param `start_colour`: the first colour of the gradient;
    :param `end_colour`: the second colour of the gradient;
    :param `direction`: the gradient direction (horizontal or vertical).
    """
    
    if direction == AUI_GRADIENT_VERTICAL:
        dc.GradientFillLinear(rect, start_colour, end_colour, wx.SOUTH)
    else:
        dc.GradientFillLinear(rect, start_colour, end_colour, wx.EAST)
        

def FindFocusDescendant(ancestor):
    """
    Find a window with the focus, that is also a descendant of the given window.
    This is used to determine the window to initially send commands to.

    :param `ancestor`: the window to check for ancestry.    
    """

    # Process events starting with the window with the focus, if any.
    focusWin = wx.Window.FindFocus()
    win = focusWin

    # Check if this is a descendant of this frame.
    # If not, win will be set to NULL.
    while win:
        if win == ancestor:
            break
        else:
            win = win.GetParent()

    if win is None:
        focusWin = None

    return focusWin


def GetLabelSize(dc, label, vertical):
    """
    Returns the L{AuiToolBar} item label size.

    :param `label`: the toolbar tool label;
    :param `vertical`: whether the toolbar tool orientation is vertical or not.
    """

    text_width = text_height = 0

    # get the text height
    dummy, text_height = dc.GetTextExtent("ABCDHgj")
    # get the text width
    if label.strip():
        text_width, dummy = dc.GetTextExtent(label)

    if vertical:
        tmp = text_height
        text_height = text_width
        text_width = tmp

    return wx.Size(text_width, text_height)


#---------------------------------------------------------------------------
# TabDragImage implementation
# This class handles the creation of a custom image when dragging
# AuiNotebook tabs
#---------------------------------------------------------------------------

class TabDragImage(wx.DragImage):
    """
    This class handles the creation of a custom image in case of drag and
    drop of a notebook tab.
    """

    def __init__(self, notebook, page, button_state, tabArt):
        """
        Default class constructor.
        
        For internal use: do not call it in your code!

        :param `notebook`: an instance of L{AuiNotebook};
        :param `page`: the dragged L{AuiNotebook} page;
        :param `button_state`: the state of the close button on the tab;
        :param `tabArt`: an instance of L{AuiDefaultTabArt} or one of its derivations.
        """

        self._backgroundColour = wx.NamedColour("pink")        
        self._bitmap = self.CreateBitmap(notebook, page, button_state, tabArt)
        wx.DragImage.__init__(self, self._bitmap)


    def CreateBitmap(self, notebook, page, button_state, tabArt):
        """
        Actually creates the drag and drop bitmap.

        :param `notebook`: an instance of L{AuiNotebook};
        :param `page`: the dragged L{AuiNotebook} page;
        :param `button_state`: the state of the close button on the tab;
        :param `tabArt`: an instance of L{AuiDefaultTabArt} or one of its derivations.
        """

        control = page.control
        memory = wx.MemoryDC(wx.EmptyBitmap(1, 1))

        tab_size, x_extent = tabArt.GetTabSize(memory, notebook, page.caption, page.bitmap, page.active,
                                               button_state, control)
            
        tab_width, tab_height = tab_size
        rect = wx.Rect(0, 0, tab_width, tab_height)

        bitmap = wx.EmptyBitmap(tab_width+1, tab_height+1)
        memory.SelectObject(bitmap)

        if wx.Platform == "__WXMAC__":
            memory.SetBackground(wx.TRANSPARENT_BRUSH)
        else:
            memory.SetBackground(wx.Brush(self._backgroundColour))
            
        memory.SetBackgroundMode(wx.TRANSPARENT)
        memory.Clear()

        paint_control = wx.Platform != "__WXMAC__"
        tabArt.DrawTab(memory, notebook, page, rect, button_state, paint_control=paint_control)
        
        memory.SetBrush(wx.TRANSPARENT_BRUSH)
        memory.SetPen(wx.BLACK_PEN)
        memory.DrawRoundedRectangle(0, 0, tab_width+1, tab_height+1, 2)

        memory.SelectObject(wx.NullBitmap)
        
        # Gtk and Windows unfortunatly don't do so well with transparent
        # drawing so this hack corrects the image to have a transparent
        # background.
        if wx.Platform != '__WXMAC__':
            timg = bitmap.ConvertToImage()
            if not timg.HasAlpha():
                timg.InitAlpha()
            for y in xrange(timg.GetHeight()):
                for x in xrange(timg.GetWidth()):
                    pix = wx.Colour(timg.GetRed(x, y),
                                    timg.GetGreen(x, y),
                                    timg.GetBlue(x, y))
                    if pix == self._backgroundColour:
                        timg.SetAlpha(x, y, 0)
            bitmap = timg.ConvertToBitmap()
        return bitmap        


def GetDockingImage(direction, useAero, center):
    """
    Returns the correct name of the docking bitmap depending on the input parameters.

    :param `useAero`: whether L{AuiManager} is using Aero-style or Whidbey-style docking
     images or not;
    :param `center`: whether we are looking for the center diamond-shaped bitmap or not. 
    """

    suffix = (center and [""] or ["_single"])[0]
    prefix = ""
    if useAero == 2:
        # Whidbey docking guides
        prefix = "whidbey_"
    elif useAero == 1:
        # Aero docking style
        prefix = "aero_"
        
    if direction == wx.TOP:
        bmp_unfocus = eval("%sup%s"%(prefix, suffix)).GetBitmap()
        bmp_focus = eval("%sup_focus%s"%(prefix, suffix)).GetBitmap()
    elif direction == wx.BOTTOM:
        bmp_unfocus = eval("%sdown%s"%(prefix, suffix)).GetBitmap()
        bmp_focus = eval("%sdown_focus%s"%(prefix, suffix)).GetBitmap()
    elif direction == wx.LEFT:
        bmp_unfocus = eval("%sleft%s"%(prefix, suffix)).GetBitmap()
        bmp_focus = eval("%sleft_focus%s"%(prefix, suffix)).GetBitmap()
    elif direction == wx.RIGHT:
        bmp_unfocus = eval("%sright%s"%(prefix, suffix)).GetBitmap()
        bmp_focus = eval("%sright_focus%s"%(prefix, suffix)).GetBitmap()
    else:
        bmp_unfocus = eval("%stab%s"%(prefix, suffix)).GetBitmap()
        bmp_focus = eval("%stab_focus%s"%(prefix, suffix)).GetBitmap()

    return bmp_unfocus, bmp_focus


def TakeScreenShot(rect):
    """
    Takes a screenshot of the screen at given position and size (rect).

    :param `rect`: the screen rectangle for which we want to take a screenshot.
    """

    # Create a DC for the whole screen area
    dcScreen = wx.ScreenDC()

    # Create a Bitmap that will later on hold the screenshot image
    # Note that the Bitmap must have a size big enough to hold the screenshot
    # -1 means using the current default colour depth
    bmp = wx.EmptyBitmap(rect.width, rect.height)

    # Create a memory DC that will be used for actually taking the screenshot
    memDC = wx.MemoryDC()

    # Tell the memory DC to use our Bitmap
    # all drawing action on the memory DC will go to the Bitmap now
    memDC.SelectObject(bmp)

    # Blit (in this case copy) the actual screen on the memory DC
    # and thus the Bitmap
    memDC.Blit( 0,            # Copy to this X coordinate
                0,            # Copy to this Y coordinate
                rect.width,   # Copy this width
                rect.height,  # Copy this height
                dcScreen,     # From where do we copy?
                rect.x,       # What's the X offset in the original DC?
                rect.y        # What's the Y offset in the original DC?
                )

    # Select the Bitmap out of the memory DC by selecting a new
    # uninitialized Bitmap
    memDC.SelectObject(wx.NullBitmap)

    return bmp


def RescaleScreenShot(bmp, thumbnail_size=200):
    """
    Rescales a bitmap to be 300 pixels wide (or tall) at maximum.

    :param `bmp`: the bitmap to rescale;
    :param `thumbnail_size`: the maximum size of every page thumbnail.
    """

    bmpW, bmpH = bmp.GetWidth(), bmp.GetHeight()
    img = bmp.ConvertToImage()

    newW, newH = bmpW, bmpH
    
    if bmpW > bmpH:
        if bmpW > thumbnail_size:
            ratio = bmpW/float(thumbnail_size)
            newW, newH = int(bmpW/ratio), int(bmpH/ratio)
            img.Rescale(newW, newH, wx.IMAGE_QUALITY_HIGH)
    else:
        if bmpH > thumbnail_size:
            ratio = bmpH/float(thumbnail_size)
            newW, newH = int(bmpW/ratio), int(bmpH/ratio)
            img.Rescale(newW, newH, wx.IMAGE_QUALITY_HIGH)

    newBmp = img.ConvertToBitmap()
    otherBmp = wx.EmptyBitmap(newW+5, newH+5)    

    memDC = wx.MemoryDC()
    memDC.SelectObject(otherBmp)
    memDC.SetBackground(wx.WHITE_BRUSH)
    memDC.Clear()
    
    memDC.SetPen(wx.TRANSPARENT_PEN)

    pos = 0
    for i in xrange(5, 0, -1):
        brush = wx.Brush(wx.Colour(50*i, 50*i, 50*i))
        memDC.SetBrush(brush)
        memDC.DrawRoundedRectangle(0, 0, newW+5-pos, newH+5-pos, 2)
        pos += 1

    memDC.DrawBitmap(newBmp, 0, 0, True)
     
    # Select the Bitmap out of the memory DC by selecting a new
    # uninitialized Bitmap
    memDC.SelectObject(wx.NullBitmap)

    return otherBmp


def GetSlidingPoints(rect, size, direction):
    """
    Returns the point at which the sliding in and out of a minimized pane begins.

    :param `rect`: the L{AuiToolBar} tool screen rectangle;
    :param `size`: the pane window size;
    :param `direction`: the pane docking direction.
    """

    if direction == AUI_DOCK_LEFT:
        startX, startY = rect.x + rect.width + 2, rect.y
    elif direction == AUI_DOCK_TOP:
        startX, startY = rect.x, rect.y + rect.height + 2
    elif direction == AUI_DOCK_RIGHT:
        startX, startY = rect.x - size.x - 2, rect.y
    elif direction == AUI_DOCK_BOTTOM:
        startX, startY = rect.x, rect.y - size.y - 2
    else:
        raise Exception("How did we get here?")

    caption_height = wx.SystemSettings.GetMetric(wx.SYS_CAPTION_Y)
    frame_border_x = wx.SystemSettings.GetMetric(wx.SYS_FRAMESIZE_X)
    frame_border_y = wx.SystemSettings.GetMetric(wx.SYS_FRAMESIZE_Y)
    
    stopX = size.x + caption_height + frame_border_x
    stopY = size.x + frame_border_y
    
    return startX, startY, stopX, stopY


def CopyAttributes(newArt, oldArt):
    """
    Copies pens, brushes, colours and fonts from the old tab art to the new one.

    :param `newArt`: the new instance of L{AuiDefaultTabArt};
    :param `oldArt`: the old instance of L{AuiDefaultTabArt}.
    """    
    
    attrs = dir(oldArt)

    for attr in attrs:
        if attr.startswith("_") and (attr.endswith("_colour") or attr.endswith("_font") or \
                                     attr.endswith("_font") or attr.endswith("_brush") or \
                                     attr.endswith("Pen") or attr.endswith("_pen")):
            setattr(newArt, attr, getattr(oldArt, attr))

    return newArt            

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