mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2025-07-21 12:41:10 +02:00
386 lines
11 KiB
Python
386 lines
11 KiB
Python
#----------------------------------------------------------------------------
|
|
# Name: ColourSelect.py
|
|
# Purpose: Colour Box Selection Control
|
|
#
|
|
# Author: Lorne White, Lorne.White@telusplanet.net
|
|
#
|
|
# Created: Feb 25, 2001
|
|
# Licence: wxWindows license
|
|
# Tags: phoenix-port, unittest, documented
|
|
#----------------------------------------------------------------------------
|
|
|
|
# creates a colour wxButton with selectable color
|
|
# button click provides a colour selection box
|
|
# button colour will change to new colour
|
|
# GetColour method to get the selected colour
|
|
|
|
# Updates:
|
|
# call back to function if changes made
|
|
|
|
# Cliff Wells, logiplexsoftware@earthlink.net:
|
|
# - Made ColourSelect into "is a button" rather than "has a button"
|
|
# - Added label parameter and logic to adjust the label colour according to the background
|
|
# colour
|
|
# - Added id argument
|
|
# - Rearranged arguments to more closely follow wx conventions
|
|
# - Simplified some of the code
|
|
|
|
# Cliff Wells, 2002/02/07
|
|
# - Added ColourSelect Event
|
|
|
|
# 12/01/2003 - Jeff Grimmett (grimmtooth@softhome.net)
|
|
#
|
|
# o Updated for 2.5 compatibility.
|
|
#
|
|
|
|
"""
|
|
Provides a :class:`wx.ColourSelect` button that, when clicked, will display a
|
|
colour selection dialog.
|
|
|
|
|
|
Description
|
|
===========
|
|
|
|
This module provides a :class:`wx.ColourSelect` button that, when clicked, will display a
|
|
colour selection dialog. The selected colour is displayed on the button itself.
|
|
|
|
|
|
Usage
|
|
=====
|
|
|
|
Sample usage::
|
|
|
|
import wx
|
|
import wx.lib.colourselect as csel
|
|
|
|
class MyFrame(wx.Frame):
|
|
|
|
def __init__(self, parent, title):
|
|
|
|
wx.Frame.__init__(self, parent, wx.ID_ANY, title, size=(400, 300))
|
|
self.panel = wx.Panel(self)
|
|
|
|
colour_button = csel.ColourSelect(self.panel, -1, "Choose...", wx.WHITE)
|
|
colour_button.Bind(csel.EVT_COLOURSELECT, self.OnChooseBackground)
|
|
|
|
def OnChooseBackground(self, event):
|
|
|
|
col1 = event.GetValue()
|
|
self.panel.SetBackgroundColour(col1)
|
|
event.Skip()
|
|
|
|
app = wx.App()
|
|
frame = MyFrame(None, 'Select a colour')
|
|
frame.Show()
|
|
app.MainLoop()
|
|
|
|
"""
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
import wx
|
|
import wx.lib.buttons
|
|
import functools
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
wxEVT_COMMAND_COLOURSELECT = wx.NewEventType()
|
|
|
|
class ColourSelectEvent(wx.PyCommandEvent):
|
|
"""
|
|
:class:`wx.ColourSelectEvent` is a special subclassing of :class:`wx.CommandEvent`
|
|
and it provides for a custom event sent every time the user chooses a colour.
|
|
"""
|
|
|
|
def __init__(self, id, value):
|
|
"""
|
|
Default class constructor.
|
|
|
|
:param integer `id`: the event identifier;
|
|
:param wx.Colour `value`: the colour currently selected.
|
|
"""
|
|
|
|
wx.PyCommandEvent.__init__(self, id = id)
|
|
self.SetEventType(wxEVT_COMMAND_COLOURSELECT)
|
|
self.value = value
|
|
|
|
|
|
def GetValue(self):
|
|
"""
|
|
Returns the currently selected colour.
|
|
|
|
:rtype: :class:`wx.Colour`
|
|
"""
|
|
|
|
return self.value
|
|
|
|
|
|
EVT_COLOURSELECT = wx.PyEventBinder(wxEVT_COMMAND_COLOURSELECT, 1)
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
class CustomColourData(object):
|
|
"""
|
|
A simple container for tracking custom colours to be shown in the colour
|
|
dialog, and which facilitates reuse of this collection across multiple
|
|
instances or multiple invocations of the :class:`ColourSelect` button.
|
|
"""
|
|
COUNT = 16
|
|
|
|
def __init__(self):
|
|
self._customColours = [None] * self.COUNT
|
|
|
|
|
|
@property
|
|
def Colours(self):
|
|
return self._customColours
|
|
|
|
@Colours.setter
|
|
def Colours(self, value):
|
|
# slice it into the current list to keep the same list instance
|
|
if isinstance(value, CustomColourData):
|
|
value = value.Colours
|
|
self._customColours[:] = value
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
|
|
|
|
class ColourSelect(wx.lib.buttons.GenBitmapButton):
|
|
"""
|
|
A subclass of :class:`wx.lib.buttons.GenBitmapButton` that,
|
|
when clicked, will display a colour selection dialog.
|
|
"""
|
|
|
|
def __init__(self, parent, id=wx.ID_ANY, label="", colour=wx.BLACK,
|
|
pos=wx.DefaultPosition, size=wx.DefaultSize,
|
|
callback=None, style=0):
|
|
"""
|
|
Default class constructor.
|
|
|
|
:param wx.Window `parent`: parent window. Must not be ``None``;
|
|
:param integer `id`: window identifier. A value of -1 indicates a default value;
|
|
:param string `label`: the button text label;
|
|
:param wx.Colour: a valid :class:`wx.Colour` instance, which will be the default initial
|
|
colour for this button;
|
|
:type `colour`: :class:`wx.Colour` or tuple
|
|
:param `pos`: the control position. A value of (-1, -1) indicates a default position,
|
|
chosen by either the windowing system or wxPython, depending on platform;
|
|
:type `pos`: tuple or :class:`wx.Point`
|
|
:param `size`: the control size. A value of (-1, -1) indicates a default size,
|
|
chosen by either the windowing system or wxPython, depending on platform;
|
|
:type `size`: tuple or :class:`wx.Size`
|
|
:param PyObject `callback`: a callable method/function that will be called every time
|
|
the user chooses a new colour;
|
|
:param integer `style`: the button style.
|
|
"""
|
|
|
|
size = wx.Size(*size)
|
|
if label:
|
|
mdc = wx.MemoryDC(wx.Bitmap(1,1))
|
|
w, h = mdc.GetTextExtent(label)
|
|
w += 8
|
|
h += 8
|
|
else:
|
|
w, h = 22, 22
|
|
|
|
size.width = size.width if size.width != -1 else w
|
|
size.height = size.height if size.height != -1 else h
|
|
super(ColourSelect, self).__init__(parent, id, wx.Bitmap(w,h),
|
|
pos=pos, size=size, style=style,
|
|
name='ColourSelect')
|
|
|
|
if type(colour) == type( () ):
|
|
colour = wx.Colour(*colour)
|
|
|
|
self.colour = colour
|
|
self.SetLabel(label)
|
|
self.callback = callback
|
|
bmp = self.MakeBitmap()
|
|
self.SetBitmap(bmp)
|
|
self.customColours = None
|
|
parent.Bind(wx.EVT_BUTTON, self.OnClick, self)
|
|
|
|
|
|
def GetColour(self):
|
|
"""
|
|
Returns the current colour set for the :class:`ColourSelect`.
|
|
|
|
:rtype: :class:`wx.Colour`
|
|
"""
|
|
|
|
return self.colour
|
|
|
|
|
|
def GetValue(self):
|
|
"""
|
|
Returns the current colour set for the :class:`ColourSelect`.
|
|
Same as :meth:`~ColourSelect.GetColour`.
|
|
|
|
:rtype: :class:`wx.Colour`
|
|
"""
|
|
|
|
return self.colour
|
|
|
|
|
|
def SetValue(self, colour):
|
|
"""
|
|
Sets the current colour for :class:`ColourSelect`. Same as
|
|
:meth:`~ColourSelect.SetColour`.
|
|
|
|
:param `colour`: the new colour for :class:`ColourSelect`.
|
|
:type `colour`: tuple or string or :class:`wx.Colour`
|
|
"""
|
|
|
|
self.SetColour(colour)
|
|
|
|
|
|
def SetColour(self, colour):
|
|
"""
|
|
Sets the current colour for :class:`ColourSelect`.
|
|
|
|
:param `colour`: the new colour for :class:`ColourSelect`.
|
|
:type `colour`: tuple or string or :class:`wx.Colour`
|
|
"""
|
|
|
|
self.colour = wx.Colour(colour) # use the typmap or copy an existing colour object
|
|
bmp = self.MakeBitmap()
|
|
self.SetBitmap(bmp)
|
|
|
|
|
|
def SetLabel(self, label):
|
|
"""
|
|
Sets the new text label for :class:`wx.ColourSelect`.
|
|
|
|
:param string `label`: the new text label for :class:`ColourSelect`.
|
|
"""
|
|
|
|
self.label = label
|
|
|
|
|
|
def GetLabel(self):
|
|
"""
|
|
Returns the current text label for the :class:`ColourSelect`.
|
|
|
|
:rtype: string
|
|
"""
|
|
|
|
return self.label
|
|
|
|
|
|
def GetCustomColours(self):
|
|
"""
|
|
Returns the current set of custom colour values to be shown in the
|
|
colour dialog, if supported.
|
|
|
|
:rtype: :class:`CustomColourData`
|
|
"""
|
|
return self.customColours
|
|
|
|
|
|
def SetCustomColours(self, colours):
|
|
"""
|
|
Sets the list of custom colour values to be shown in colour dialog, if
|
|
supported.
|
|
|
|
:param `colours`: An instance of :class:`CustomColourData` or a 16
|
|
element list of ``None`` or :class:`wx.Colour` values.
|
|
"""
|
|
if isinstance(colours, CustomColourData):
|
|
colours = colours.Colours
|
|
if self.customColours is None:
|
|
self.customColours = CustomColourData()
|
|
self.customColours.Colours = colours
|
|
|
|
|
|
Colour = property(GetColour, SetColour)
|
|
Value = property(GetValue, SetValue)
|
|
Label = property(GetLabel, SetLabel)
|
|
CustomColours = property(GetCustomColours, SetCustomColours)
|
|
|
|
|
|
def MakeBitmap(self):
|
|
""" Creates a bitmap representation of the current selected colour. """
|
|
|
|
bdr = 8
|
|
width, height = self.GetSize()
|
|
|
|
# yes, this is weird, but it appears to work around a bug in wxMac
|
|
if "wxMac" in wx.PlatformInfo and width == height:
|
|
height -= 1
|
|
|
|
bmp = wx.Bitmap(width-bdr, height-bdr)
|
|
dc = wx.MemoryDC()
|
|
dc.SelectObject(bmp)
|
|
dc.SetFont(self.GetFont())
|
|
label = self.GetLabel()
|
|
# Just make a little colored bitmap
|
|
dc.SetBackground(wx.Brush(self.colour))
|
|
dc.Clear()
|
|
|
|
if label:
|
|
# Add a label to it
|
|
avg = functools.reduce(lambda a, b: a + b, self.colour.Get()) / 3
|
|
fcolour = avg > 128 and wx.BLACK or wx.WHITE
|
|
dc.SetTextForeground(fcolour)
|
|
dc.DrawLabel(label, (0,0, width-bdr, height-bdr),
|
|
wx.ALIGN_CENTER)
|
|
|
|
dc.SelectObject(wx.NullBitmap)
|
|
return bmp
|
|
|
|
|
|
def SetBitmap(self, bmp):
|
|
"""
|
|
Sets the bitmap representation of the current selected colour to the button.
|
|
|
|
:param wx.Bitmap `bmp`: the new bitmap.
|
|
"""
|
|
|
|
self.SetBitmapLabel(bmp)
|
|
self.Refresh()
|
|
|
|
|
|
def OnChange(self):
|
|
""" Fires the ``EVT_COLOURSELECT`` event, as the user has changed the current colour. """
|
|
|
|
evt = ColourSelectEvent(self.GetId(), self.GetValue())
|
|
evt.SetEventObject(self)
|
|
wx.PostEvent(self, evt)
|
|
if self.callback is not None:
|
|
self.callback()
|
|
|
|
|
|
def OnClick(self, event):
|
|
"""
|
|
Handles the ``wx.EVT_BUTTON`` event for :class:`ColourSelect`.
|
|
|
|
:param `event`: a :class:`wx.CommandEvent` event to be processed.
|
|
"""
|
|
|
|
data = wx.ColourData()
|
|
data.SetChooseFull(True)
|
|
data.SetColour(self.colour)
|
|
if self.customColours:
|
|
for idx, clr in enumerate(self.customColours.Colours):
|
|
if clr is not None:
|
|
data.SetCustomColour(idx, clr)
|
|
|
|
dlg = wx.ColourDialog(wx.GetTopLevelParent(self), data)
|
|
changed = dlg.ShowModal() == wx.ID_OK
|
|
|
|
if changed:
|
|
data = dlg.GetColourData()
|
|
self.SetColour(data.GetColour())
|
|
if self.customColours:
|
|
self.customColours.Colours = \
|
|
[data.GetCustomColour(idx) for idx in range(0, 16)]
|
|
|
|
dlg.Destroy()
|
|
|
|
# moved after dlg.Destroy, since who knows what the callback will do...
|
|
if changed:
|
|
self.OnChange()
|
|
|