Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Color picker dialog for Color objects/PyfaceColor trait #711

Merged
merged 5 commits into from
Sep 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions examples/color_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# (C) Copyright 2005-2021 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

from pyface.color_dialog import get_color

# display a color dialog and get the result
color = get_color(None, color='red')
if color is not None:
print(color.hex())
44 changes: 44 additions & 0 deletions pyface/color_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# (C) Copyright 2005-2021 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

""" The implementation of a dialog that allows the user to select a color.
"""

from .constant import OK
from .toolkit import toolkit_object


ColorDialog = toolkit_object("color_dialog:ColorDialog")


def get_color(parent, color, show_alpha=False):
""" Convenience function that displays a color dialog.

Parameters
----------
parent : toolkit control
The parent toolkit control for the modal dialog.
color : Color or color description
The initial Color object, rgb(a) tuple or a string holding a valid
color description.
show_alpha : bool
Whether or not to show alpha channel information.

Returns
-------
color : Color or None
The selected color, or None if the user made no selection.
"""
dialog = ColorDialog(parent=parent, color=color, show_alpha=show_alpha)
result = dialog.open()
if result == OK:
return dialog.color
else:
return None
29 changes: 29 additions & 0 deletions pyface/i_color_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# (C) Copyright 2005-2021 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

""" The interface for a dialog that allows the user to select a color. """

from traits.api import Bool

from pyface.ui_traits import PyfaceColor
from pyface.i_dialog import IDialog


class IColorDialog(IDialog):
""" The interface for a dialog that allows the user to choose a color.
"""

# 'IColorDialog' interface ---------------------------------------------#

#: The color in the dialog.
color = PyfaceColor()

#: Whether or not to allow the user to chose an alpha value.
show_alpha = Bool(False)
95 changes: 95 additions & 0 deletions pyface/tests/test_color_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# (C) Copyright 2005-2021 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!


import unittest

from ..color import Color
from ..color_dialog import ColorDialog, get_color
from ..toolkit import toolkit_object

GuiTestAssistant = toolkit_object("util.gui_test_assistant:GuiTestAssistant")
no_gui_test_assistant = GuiTestAssistant.__name__ == "Unimplemented"

ModalDialogTester = toolkit_object(
"util.modal_dialog_tester:ModalDialogTester"
)
no_modal_dialog_tester = ModalDialogTester.__name__ == "Unimplemented"


@unittest.skipIf(no_gui_test_assistant, "No GuiTestAssistant")
class TestColorDialog(unittest.TestCase, GuiTestAssistant):

def setUp(self):
GuiTestAssistant.setUp(self)
self.dialog = ColorDialog(color="rebeccapurple")

def tearDown(self):
if self.dialog.control is not None:
with self.delete_widget(self.dialog.control):
self.dialog.destroy()
del self.dialog
GuiTestAssistant.tearDown(self)

def test_color(self):
# test that colors are translated as expected
self.dialog.color = "red"

self.assertEqual(self.dialog.color, Color.from_str("red"))

def test_create(self):
# test that creation and destruction works as expected
with self.event_loop():
self.dialog._create()
with self.event_loop():
self.dialog.destroy()

def test_destroy(self):
# test that destroy works even when no control
with self.event_loop():
self.dialog.destroy()

def test_close(self):
# test that close works
with self.event_loop():
self.dialog._create()
with self.event_loop():
self.dialog.close()

def test_show_alpha(self):
# test that creation and destruction works with show_alpha True
self.dialog.show_alpha = True

with self.event_loop():
self.dialog._create()


@unittest.skipIf(no_gui_test_assistant, "No GuiTestAssistant")
class TestGetColor(unittest.TestCase, GuiTestAssistant):

@unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
def test_close(self):
# test that cancel works as expected
tester = ModalDialogTester(
lambda: get_color(None, "rebeccapurple")
)
tester.open_and_run(when_opened=lambda x: x.close(accept=False))

self.assertEqual(tester.result, None)

@unittest.skipIf(no_modal_dialog_tester, "ModalDialogTester unavailable")
def test_close_show_alpha(self):
# test that cancel works as expected
tester = ModalDialogTester(
lambda: get_color(None, "rebeccapurple", True)
)
tester.open_and_run(when_opened=lambda x: x.close(accept=False))

self.assertEqual(tester.result, None)
63 changes: 63 additions & 0 deletions pyface/ui/qt4/color_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# (C) Copyright 2005-2021 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

""" A dialog that allows the user to select a color. """

from pyface.qt import QtGui

from traits.api import Bool, provides

from pyface.color import Color
from pyface.ui_traits import PyfaceColor
from pyface.i_color_dialog import IColorDialog
from .dialog import Dialog


@provides(IColorDialog)
class ColorDialog(Dialog):
""" A dialog that allows the user to choose a color.
"""

# 'IColorDialog' interface ----------------------------------------------

#: The color in the dialog.
color = PyfaceColor()

#: Whether or not to allow the user to chose an alpha value.
show_alpha = Bool(False)

# ------------------------------------------------------------------------
# 'IDialog' interface.
# ------------------------------------------------------------------------

def _create_contents(self, parent):
# In PyQt this is a canned dialog so there are no contents.
pass

# ------------------------------------------------------------------------
# 'IWindow' interface.
# ------------------------------------------------------------------------

def close(self):
if self.control.result() == QtGui.QDialog.Accepted:
qcolor = self.control.selectedColor()
self.color = Color.from_toolkit(qcolor)
return super(ColorDialog, self).close()

# ------------------------------------------------------------------------
# 'IWindow' interface.
# ------------------------------------------------------------------------

def _create_control(self, parent):
qcolor = self.color.to_toolkit()
dialog = QtGui.QColorDialog(qcolor, parent)
if self.show_alpha:
dialog.setOptions(QtGui.QColorDialog.ShowAlphaChannel)
return dialog
70 changes: 70 additions & 0 deletions pyface/ui/wx/color_dialog.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# (C) Copyright 2005-2021 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

""" The interface for a dialog that allows the user to select a color. """

import wx

from traits.api import Bool, provides

from pyface.color import Color
from pyface.ui_traits import PyfaceColor
from pyface.i_color_dialog import IColorDialog
from .dialog import Dialog

# The WxPython version in a convenient to compare form.
wx_version = tuple(int(x) for x in wx.__version__.split('.')[:3])


@provides(IColorDialog)
class ColorDialog(Dialog):
""" A dialog for selecting colors.
"""

# 'IColorDialog' interface ----------------------------------------------

#: The color in the dialog.
color = PyfaceColor()

#: Whether or not to allow the user to chose an alpha value. Only works
#: for wxPython 4.1 and higher.
show_alpha = Bool(False)

# ------------------------------------------------------------------------
# 'IDialog' interface.
# ------------------------------------------------------------------------

def _create_contents(self, parent):
# In wx this is a canned dialog.
pass

# ------------------------------------------------------------------------
# 'IWindow' interface.
# ------------------------------------------------------------------------

def close(self):
if self.control.GetReturnCode() == wx.ID_OK:
colour_data = self.control.GetColourData()
wx_colour = colour_data.GetColour()
self.color = Color.from_toolkit(wx_colour)
super(ColorDialog, self).close()

# ------------------------------------------------------------------------
# 'IWidget' interface.
# ------------------------------------------------------------------------

def _create_control(self, parent):
wx_colour = self.color.to_toolkit()
data = wx.ColourData()
data.SetColour(wx_colour)
if wx_version >= (4, 1):
data.SetChooseAlpha(self.show_alpha)
dialog = wx.ColourDialog(parent, data)
return dialog