Skip to content

Commit

Permalink
coclor dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
PingHsunTsai committed Jun 26, 2024
1 parent 16edc44 commit 8942580
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 108 deletions.
157 changes: 157 additions & 0 deletions src/compas_viewer/components/color.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
from typing import TYPE_CHECKING

from PySide6.QtGui import QColor
from PySide6.QtWidgets import QColorDialog
from PySide6.QtWidgets import QPushButton
from PySide6.QtWidgets import QVBoxLayout
from PySide6.QtWidgets import QWidget

from compas.colors import Color
from compas.colors.colordict import ColorDict
from compas_viewer.base import Base
from compas_viewer.components.combobox import ComboBox

if TYPE_CHECKING:
from compas_viewer.scene import ViewerSceneObject


def remap_rgb(value, to_range_one=True):
"""
Remap an RGB value between the range (0, 255) and (0, 1).
Parameters
----------
value : tuple
The RGB value to remap.
to_range_one : bool, optional
If True, remap from (0, 255) to (0, 1). If False, remap from (0, 1) to (0, 255).
Returns
-------
tuple
The remapped RGB value.
"""
factor = 1 / 255 if to_range_one else 255
return tuple(v * factor for v in value)


class ColorComboBox(QWidget, Base):
"""
A custom QWidget for selecting colors from a predefined list and applying the selected color to an object's attribute.
Parameters
----------
obj : ViewerSceneObject, optional
The object to which the selected color will be applied. Defaults to None.
attr : str, optional
The attribute of the object to which the selected color will be applied. Defaults to None.
Attributes
----------
obj : ViewerSceneObject
The object to which the selected color will be applied.
attr : str
The attribute of the object to which the selected color will be applied.
color_options : list of QColor
A list of predefined QColor objects representing available colors.
layout : QVBoxLayout
The layout of the widget.
color_selector : ComboBox
A combo box for selecting colors.
Methods
-------
change_color(color: QColor) -> None
Changes the color of the object's attribute to the selected color.
Example
-------
>>> color_combobox = ColorComboBox(obj=some_obj, attr="linecolor")
>>> color_combobox.show()
"""

def __init__(
self,
obj: "ViewerSceneObject" = None,
attr: str = None,
):
super().__init__()
self.obj = obj
self.attr = attr

self.color_options = [
QColor(255, 255, 255), # White
QColor(211, 211, 211), # LightGray
QColor(190, 190, 190), # Gray
QColor(0, 0, 0), # Black
QColor(255, 0, 0), # Red
QColor(0, 255, 0), # Green
QColor(0, 0, 255), # Blue
QColor(255, 255, 0), # Yellow
QColor(0, 255, 255), # Cyan
QColor(255, 0, 255), # Magenta
]

default_color = getattr(self.obj, self.attr)

if isinstance(default_color, Color):
default_color = default_color.rgb
elif isinstance(default_color, ColorDict):
default_color = default_color.default
else:
raise ValueError("Invalid color type.")
default_color = QColor(*remap_rgb(default_color, to_range_one=False))

self.layout = QVBoxLayout(self)
self.color_selector = ComboBox(self.color_options, self.change_color, paint=True)
self.color_selector.setAssignedColor(default_color)
self.layout.addWidget(self.color_selector)

def change_color(self, color):
rgb = remap_rgb(color.getRgb())[:-1] # rgba to rgb(0-1)
setattr(self.obj, self.attr, Color(*rgb))
self.obj.update()


class ColorButton(QWidget):
def __init__(
self,
obj: "ViewerSceneObject" = None,
attr: str = None,
):
super().__init__()

self.obj = obj
self.attr = attr

default_color = getattr(self.obj, self.attr)
if isinstance(default_color, Color):
default_color = default_color.rgb
elif isinstance(default_color, ColorDict):
default_color = default_color.default
else:
raise ValueError("Invalid color type.")
default_color = QColor(*remap_rgb(default_color, to_range_one=False))

self.color_button = QPushButton(self)
self.layout = QVBoxLayout(self)
self.layout.addWidget(self.color_button)
self.color_button.clicked.connect(self.open_color_dialog)
self.set_button_color(default_color)

def open_color_dialog(self):
color = QColorDialog.getColor()

if color.isValid():
self.change_color(color)
self.set_button_color(color)

def set_button_color(self, color: QColor):
self.color_button.setStyleSheet(f"background-color: {color.name()};")
self.color_button.setText(color.name())
self.current_color = color

def change_color(self, color):
rgb = remap_rgb(color.getRgb())[:-1] # rgba to rgb(0-1)
setattr(self.obj, self.attr, Color(*rgb))
self.obj.update()
104 changes: 0 additions & 104 deletions src/compas_viewer/components/combobox.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from typing import TYPE_CHECKING
from typing import Callable
from typing import Optional

Expand All @@ -11,33 +10,8 @@
from PySide6.QtWidgets import QVBoxLayout
from PySide6.QtWidgets import QWidget

from compas.colors import Color
from compas.colors.colordict import ColorDict
from compas_viewer.base import Base

if TYPE_CHECKING:
from compas_viewer.scene import ViewerSceneObject


def remap_rgb(value, to_range_one=True):
"""
Remap an RGB value between the range (0, 255) and (0, 1).
Parameters
----------
value : tuple
The RGB value to remap.
to_range_one : bool, optional
If True, remap from (0, 255) to (0, 1). If False, remap from (0, 1) to (0, 255).
Returns
-------
tuple
The remapped RGB value.
"""
factor = 1 / 255 if to_range_one else 255
return tuple(v * factor for v in value)


class ColorDelegate(QStyledItemDelegate):
def paint(self, painter, option, index):
Expand Down Expand Up @@ -171,84 +145,6 @@ def paintEvent(self, event) -> None:
painter.end()


class ColorComboBox(QWidget, Base):
"""
A custom QWidget for selecting colors from a predefined list and applying the selected color to an object's attribute.
Parameters
----------
obj : ViewerSceneObject, optional
The object to which the selected color will be applied. Defaults to None.
attr : str, optional
The attribute of the object to which the selected color will be applied. Defaults to None.
Attributes
----------
obj : ViewerSceneObject
The object to which the selected color will be applied.
attr : str
The attribute of the object to which the selected color will be applied.
color_options : list of QColor
A list of predefined QColor objects representing available colors.
layout : QVBoxLayout
The layout of the widget.
color_selector : ComboBox
A combo box for selecting colors.
Methods
-------
change_color(color: QColor) -> None
Changes the color of the object's attribute to the selected color.
Example
-------
>>> color_combobox = ColorComboBox(obj=some_obj, attr="linecolor")
>>> color_combobox.show()
"""

def __init__(
self,
obj: "ViewerSceneObject" = None,
attr: str = None,
):
super().__init__()
self.obj = obj
self.attr = attr

self.color_options = [
QColor(255, 255, 255), # White
QColor(211, 211, 211), # LightGray
QColor(190, 190, 190), # Gray
QColor(0, 0, 0), # Black
QColor(255, 0, 0), # Red
QColor(0, 255, 0), # Green
QColor(0, 0, 255), # Blue
QColor(255, 255, 0), # Yellow
QColor(0, 255, 255), # Cyan
QColor(255, 0, 255), # Magenta
]

default_color = getattr(self.obj, self.attr)

if isinstance(default_color, Color):
default_color = default_color.rgb
elif isinstance(default_color, ColorDict):
default_color = default_color.default
else:
raise ValueError("Invalid color type.")
default_color = QColor(*remap_rgb(default_color, to_range_one=False))

self.layout = QVBoxLayout(self)
self.color_selector = ComboBox(self.color_options, self.change_color, paint=True)
self.color_selector.setAssignedColor(default_color)
self.layout.addWidget(self.color_selector)

def change_color(self, color):
rgb = remap_rgb(color.getRgb())[:-1] # rgba to rgb(0-1)
setattr(self.obj, self.attr, Color(*rgb))
self.obj.update()


class ViewModeAction(QWidget, Base):
def __init__(self):
super().__init__()
Expand Down
6 changes: 5 additions & 1 deletion src/compas_viewer/components/layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from PySide6.QtWidgets import QLayout
from PySide6.QtWidgets import QVBoxLayout

from compas_viewer.components.combobox import ColorComboBox
from compas_viewer.components.color import ColorButton
from compas_viewer.components.color import ColorComboBox
from compas_viewer.components.double_edit import DoubleEdit
from compas_viewer.components.label import LabelWidget
from compas_viewer.components.textedit import TextEdit
Expand Down Expand Up @@ -84,6 +85,9 @@ def base_layout(items: list) -> tuple[QVBoxLayout, dict]:
widget = TextEdit(text=text)
right_layout.addWidget(widget)
widgets[f"{l_title}_{type}"] = widget
elif type == "color_dialog":
widget = ColorButton(obj=obj, attr=attr)
right_layout.addWidget(widget)

sub_layout.addLayout(left_layout)
sub_layout.addLayout(right_layout)
Expand Down
6 changes: 3 additions & 3 deletions src/compas_viewer/components/objectsetting.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ def object_setting_layout(viewer: "Viewer"):
status = True
new_items = [
{"title": "Name", "items": [{"type": "text_edit", "text": str(obj.name)}]},
{"title": "Point_Color", "items": [{"type": "color_combobox", "obj": obj, "attr": "pointcolor"}]},
{"title": "Line_Color", "items": [{"type": "color_combobox", "obj": obj, "attr": "linecolor"}]},
{"title": "Face_Color", "items": [{"type": "color_combobox", "obj": obj, "attr": "facecolor"}]},
{"title": "Point_Color", "items": [{"type": "color_dialog", "obj": obj, "attr": "pointcolor"}]},
{"title": "Line_Color", "items": [{"type": "color_dialog", "obj": obj, "attr": "linecolor"}]},
{"title": "Face_Color", "items": [{"type": "color_dialog", "obj": obj, "attr": "facecolor"}]},
{"title": "Line_Width", "items": [{"type": "double_edit", "value": obj.linewidth, "min_val": 0.0, "max_val": 10.0}]},
{"title": "Point_Size", "items": [{"type": "double_edit", "value": obj.pointsize, "min_val": 0.0, "max_val": 10.0}]},
{"title": "Opacity", "items": [{"type": "double_edit", "value": obj.opacity, "min_val": 0.0, "max_val": 1.0}]},
Expand Down

0 comments on commit 8942580

Please sign in to comment.