mirror of
https://github.com/wxWidgets/Phoenix.git
synced 2026-01-07 20:40:11 +01:00
Fixed colourchooser palette and colour_slider controls.
Palette box and slider box are now sized to fit their content, making the whole area accessible. Colour slider is now clickable.
This commit is contained in:
@@ -80,13 +80,16 @@ class Canvas(wx.Window):
|
||||
"""
|
||||
def __init__(self, parent, id,
|
||||
pos=wx.DefaultPosition,
|
||||
size=wx.DefaultSize,
|
||||
style=wx.SIMPLE_BORDER):
|
||||
style=wx.SIMPLE_BORDER,
|
||||
forceClientSize=None):
|
||||
"""Creates a canvas instance and initializes the off-screen
|
||||
buffer. Also sets the handler for rendering the canvas
|
||||
automatically via size and paint calls from the windowing
|
||||
system."""
|
||||
wx.Window.__init__(self, parent, id, pos, size, style)
|
||||
wx.Window.__init__(self, parent, id, pos, style=style)
|
||||
if forceClientSize:
|
||||
self.SetMaxClientSize(forceClientSize)
|
||||
self.SetMinClientSize(forceClientSize)
|
||||
|
||||
# Perform an intial sizing
|
||||
self.ReDraw()
|
||||
@@ -96,7 +99,7 @@ class Canvas(wx.Window):
|
||||
self.Bind(wx.EVT_PAINT, self.onPaint)
|
||||
|
||||
def MakeNewBuffer(self):
|
||||
size = self.GetSize()
|
||||
size = self.GetClientSize()
|
||||
self.buffer = BitmapBuffer(size[0], size[1],
|
||||
self.GetBackgroundColour())
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ class PyColourBox(wx.Panel):
|
||||
"""Sets the box's current couple to the given tuple."""
|
||||
self.colour = colour
|
||||
self.colour_box.SetBackgroundColour(wx.Colour(*self.colour))
|
||||
self.colour_box.Refresh()
|
||||
|
||||
def Update(self):
|
||||
wx.Panel.Update(self)
|
||||
|
||||
@@ -28,6 +28,7 @@ from __future__ import absolute_import
|
||||
# Tags: phoenix-port
|
||||
|
||||
import wx
|
||||
import wx.lib.newevent as newevent
|
||||
|
||||
from . import pycolourbox
|
||||
from . import pypalette
|
||||
@@ -37,6 +38,19 @@ from . import intl
|
||||
|
||||
from .intl import _ # _
|
||||
|
||||
ColourChangedEventBase, EVT_COLOUR_CHANGED = newevent.NewEvent()
|
||||
|
||||
class ColourChangedEvent(ColourChangedEventBase):
|
||||
"""Adds GetColour()/GetValue() for compatibility with ColourPickerCtrl and colourselect"""
|
||||
def __init__(self, newColour):
|
||||
super().__init__(newColour = newColour)
|
||||
|
||||
def GetColour(self):
|
||||
return self.newColour
|
||||
|
||||
def GetValue(self):
|
||||
return self.newColour
|
||||
|
||||
class PyColourChooser(wx.Panel):
|
||||
"""A Pure-Python implementation of the colour chooser dialog.
|
||||
|
||||
@@ -169,6 +183,8 @@ class PyColourChooser(wx.Panel):
|
||||
|
||||
self.palette = pypalette.PyPalette(self, -1)
|
||||
self.colour_slider = pycolourslider.PyColourSlider(self, -1)
|
||||
self.colour_slider.Bind(wx.EVT_LEFT_DOWN, self.onSliderDown)
|
||||
self.colour_slider.Bind(wx.EVT_MOTION, self.onSliderMotion)
|
||||
self.slider = wx.Slider(
|
||||
self, self.idSCROLL, 86, 0, self.colour_slider.HEIGHT - 1,
|
||||
style=wx.SL_VERTICAL, size=(15, self.colour_slider.HEIGHT)
|
||||
@@ -185,7 +201,6 @@ class PyColourChooser(wx.Panel):
|
||||
self.palette.Bind(wx.EVT_LEFT_DOWN, self.onPaletteDown)
|
||||
self.palette.Bind(wx.EVT_LEFT_UP, self.onPaletteUp)
|
||||
self.palette.Bind(wx.EVT_MOTION, self.onPaletteMotion)
|
||||
self.mouse_down = False
|
||||
|
||||
self.solid = pycolourbox.PyColourBox(self, -1, size=(75, 50))
|
||||
slabel = wx.StaticText(self, -1, _("Solid Colour"))
|
||||
@@ -366,11 +381,17 @@ class PyColourChooser(wx.Panel):
|
||||
s = 0
|
||||
|
||||
return self.hsvToColour((h, s, v))
|
||||
|
||||
def updateDisplayColour(self, colour):
|
||||
"""Update the displayed color box (solid) and send the EVT_COLOUR_CHANGED"""
|
||||
self.solid.SetColour(colour)
|
||||
evt = ColourChangedEvent(newColour=colour)
|
||||
wx.PostEvent(self, evt)
|
||||
|
||||
def UpdateColour(self, colour):
|
||||
"""Updates displayed colour and HSV controls with the new colour"""
|
||||
# Set the color info
|
||||
self.solid.SetColour(colour)
|
||||
self.updateDisplayColour(colour)
|
||||
self.colour_slider.SetBaseColour(colour)
|
||||
self.colour_slider.ReDraw()
|
||||
|
||||
@@ -404,22 +425,55 @@ class PyColourChooser(wx.Panel):
|
||||
self.hentry.SetValue("%.2f" % (h))
|
||||
self.sentry.SetValue("%.2f" % (s))
|
||||
self.ventry.SetValue("%.2f" % (v))
|
||||
|
||||
def onColourSliderClick(self, y):
|
||||
"""Shared helper for onSliderDown()/onSliderMotion()"""
|
||||
v = self.colour_slider.GetVFromClick(y)
|
||||
self.setSliderToV(v)
|
||||
|
||||
# Now with the slider updated, update all controls
|
||||
colour = self.getColourFromControls()
|
||||
|
||||
self.updateDisplayColour(colour) # Update display
|
||||
self.UpdateEntries(colour)
|
||||
|
||||
# We don't move on the palette...
|
||||
|
||||
# width, height = self.palette.GetSize()
|
||||
# x = width * h
|
||||
# y = height * (1 - s)
|
||||
# self.palette.HighlightPoint(x, y)
|
||||
|
||||
def onSliderDown(self, event):
|
||||
"""Handle mouse click on the colour slider palette"""
|
||||
self.onColourSliderClick(event.GetY())
|
||||
|
||||
def onSliderMotion(self, event):
|
||||
"""Handle mouse-down drag on the colour slider palette"""
|
||||
if event.LeftIsDown():
|
||||
self.onColourSliderClick(event.GetY())
|
||||
|
||||
def onPaletteDown(self, event):
|
||||
"""Stores state that the mouse has been pressed and updates
|
||||
the selected colour values."""
|
||||
self.mouse_down = True
|
||||
self.doPaletteClick(event.GetX(), event.GetY())
|
||||
|
||||
# Prevent mouse from leaving window, so that we will also get events
|
||||
# when mouse is dragged along the edges of the rectangle.
|
||||
self.palette.CaptureMouse()
|
||||
|
||||
def onPaletteUp(self, event):
|
||||
"""Stores state that the mouse is no longer depressed."""
|
||||
self.mouse_down = False
|
||||
self.palette.ReleaseMouse() # Must call once for each CaputreMouse()
|
||||
|
||||
def onPaletteMotion(self, event):
|
||||
"""Updates the colour values during mouse motion while the
|
||||
mouse button is depressed."""
|
||||
if self.mouse_down:
|
||||
if event.LeftIsDown():
|
||||
self.doPaletteClick(event.GetX(), event.GetY())
|
||||
|
||||
def onPaletteCaptureLost(self, event):
|
||||
pass # I don't think we have to call ReleaseMouse in this event
|
||||
|
||||
def doPaletteClick(self, m_x, m_y):
|
||||
"""Updates the colour values based on the mouse location
|
||||
@@ -433,7 +487,7 @@ class PyColourChooser(wx.Panel):
|
||||
|
||||
colour = self.getColourFromControls()
|
||||
|
||||
self.solid.SetColour(colour) # Update display
|
||||
self.updateDisplayColour(colour) # Update display
|
||||
self.UpdateEntries(colour)
|
||||
|
||||
# Highlight a fresh selected area
|
||||
@@ -443,7 +497,7 @@ class PyColourChooser(wx.Panel):
|
||||
"""Updates the display to reflect the new "Value"."""
|
||||
value = self.slider.GetValue()
|
||||
colour = self.getColourFromControls()
|
||||
self.solid.SetColour(colour)
|
||||
self.updateDisplayColour(colour)
|
||||
self.UpdateEntries(colour)
|
||||
|
||||
def getValueAsFloat(self, textctrl):
|
||||
@@ -537,8 +591,12 @@ def main():
|
||||
|
||||
def onClick(self, cmdEvt):
|
||||
with CCTestDialog(self, self.box.GetColour()) as dialog:
|
||||
dialog.chooser.Bind(EVT_COLOUR_CHANGED, self.onColourChanged)
|
||||
dialog.ShowModal()
|
||||
self.box.SetColour(dialog.chooser.GetValue())
|
||||
|
||||
def onColourChanged(self, event):
|
||||
self.box.SetColour(event.GetValue())
|
||||
|
||||
class App(wx.App):
|
||||
def OnInit(self):
|
||||
|
||||
@@ -54,7 +54,7 @@ class PyColourSlider(canvas.Canvas):
|
||||
# drawing function
|
||||
self.SetBaseColour(colour)
|
||||
|
||||
canvas.Canvas.__init__(self, parent, id, size=(self.WIDTH, self.HEIGHT))
|
||||
canvas.Canvas.__init__(self, parent, id, forceClientSize=(self.WIDTH, self.HEIGHT))
|
||||
|
||||
def SetBaseColour(self, colour):
|
||||
"""Sets the base, or target colour, to use as the central colour
|
||||
@@ -66,11 +66,17 @@ class PyColourSlider(canvas.Canvas):
|
||||
the slider."""
|
||||
return self.base_colour
|
||||
|
||||
def GetValue(self, pos):
|
||||
"""Returns the colour value for a position on the slider. The position
|
||||
must be within the valid height of the slider, or results can be
|
||||
unpredictable."""
|
||||
return self.buffer.GetPixelColour(0, pos)
|
||||
def GetVFromClick(self, pos):
|
||||
"""
|
||||
Returns the HSV value "V" based on the location of a mouse click at y offset "pos"
|
||||
"""
|
||||
_, height = self.GetClientSize()
|
||||
if pos < 0:
|
||||
return 1 # Snap to max
|
||||
if pos >= height - 1:
|
||||
return 0 # Snap to 0
|
||||
|
||||
return 1 - (pos / self.HEIGHT)
|
||||
|
||||
def DrawBuffer(self):
|
||||
"""Actual implementation of the widget's drawing. We simply draw
|
||||
|
||||
@@ -37,6 +37,9 @@ import colorsys
|
||||
|
||||
from wx.lib.embeddedimage import PyEmbeddedImage
|
||||
|
||||
# Size of Image
|
||||
IMAGE_SIZE = (200,192)
|
||||
|
||||
Image = PyEmbeddedImage(
|
||||
"iVBORw0KGgoAAAANSUhEUgAAAMgAAADACAYAAABBCyzzAAAABHNCSVQICAgIfAhkiAAACwNJ"
|
||||
"REFUeJztnc16o0YQRZHt8SJZJO//lMkiWWQsKwsLK7S49dNdjTyTczYYhBBd7vqoom7B6bIs"
|
||||
@@ -112,7 +115,7 @@ class PyPalette(canvas.Canvas):
|
||||
|
||||
HORIZONTAL_STEP = 2
|
||||
VERTICAL_STEP = 4
|
||||
|
||||
|
||||
def __init__(self, parent, id):
|
||||
"""Creates a palette object."""
|
||||
# Load the pre-generated palette XPM
|
||||
@@ -124,21 +127,35 @@ class PyPalette(canvas.Canvas):
|
||||
|
||||
self.palette = Image.GetBitmap()
|
||||
self.point = None
|
||||
canvas.Canvas.__init__ (self, parent, id, size=(200, 192))
|
||||
|
||||
canvas.Canvas.__init__ (self, parent, id, forceClientSize=IMAGE_SIZE)
|
||||
|
||||
def DoGetBestClientSize(self):
|
||||
"""Overridden to create a client window that exactly fits our bitmap"""
|
||||
return self.palette.GetSize()
|
||||
|
||||
def xInBounds(self, x):
|
||||
"""Limit x to [0,width)"""
|
||||
if x < 0:
|
||||
x = 0
|
||||
if x >= self.buffer.width:
|
||||
x = self.buffer.width - 1
|
||||
return x
|
||||
|
||||
def yInBounds(self, y):
|
||||
"""Limit y to [0,height)"""
|
||||
if y < 0:
|
||||
y = 0
|
||||
if y >= self.buffer.height:
|
||||
y = self.buffer.height - 1
|
||||
return y
|
||||
|
||||
def GetValue(self, x, y):
|
||||
"""Returns a colour value at a specific x, y coordinate pair. This
|
||||
is useful for determining the colour found a specific mouse click
|
||||
in an external event handler."""
|
||||
if x < 0:
|
||||
x = 0
|
||||
if y < 0:
|
||||
y = 0
|
||||
if x >= self.buffer.width:
|
||||
x = self.buffer.width - 1
|
||||
if y >= self.buffer.height:
|
||||
y = self.buffer.height - 1
|
||||
|
||||
x = self.xInBounds(x)
|
||||
y = self.yInBounds(y)
|
||||
return self.buffer.GetPixelColour(x, y)
|
||||
|
||||
def DrawBuffer(self):
|
||||
@@ -154,7 +171,7 @@ class PyPalette(canvas.Canvas):
|
||||
def HighlightPoint(self, x, y):
|
||||
"""Highlights an area of the palette with a little circle around
|
||||
the coordinate point"""
|
||||
self.point = (x, y)
|
||||
self.point = (self.xInBounds(x), self.yInBounds(y))
|
||||
self.ReDraw()
|
||||
|
||||
def ClearPoint(self):
|
||||
|
||||
Reference in New Issue
Block a user