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

Multiselect-dropdown-foreground-background #590

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
34 changes: 34 additions & 0 deletions client_code/Demo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#
# This software is published at https://github.com/anvilistas/anvil-extras
import anvil.http
from anvil import Button

from ..popover import popover
from ..utils import auto_refreshing
from ._anvil_designer import DemoTemplate

Expand All @@ -32,6 +34,11 @@ def __init__(self, **properties):
self.pivot.items = anvil.http.request(dataset_url, json=True)
self.init_components(**properties)

self.popover_button = Button(text="Open the popup")
self.popover_button.add_event_handler("click", self.popup_button_click)
self.popover = popover(self.popover_button, "test popup colors")
self.add_component(self.popover_button)

def timer_1_tick(self, **event_args):
if self.progress <= 1:
self.progress_bar.progress = self.progress
Expand Down Expand Up @@ -142,3 +149,30 @@ def chips_1_chips_changed(self, **event_args):

def autocomplete_event(self, event_name, **event_args):
print(event_name, self.item["text"])

def change_multi_color(self, **event_args):
self.multi_select_drop_down_1.background = "blue"
self.multi_select_drop_down_1.foreground = "red"
self.multi_select_drop_down_1.items += ["another item"]

def remove_multi_color(self, **event_args):
self.multi_select_drop_down_1.background = ""
self.multi_select_drop_down_1.foreground = ""
self.multi_select_drop_down_1.items = self.multi_select_drop_down_1.items

def popup_button_click(self, **event_args):
if self.popover.foreground == "red":
self.popover.foreground = "blue"
elif self.popover.foreground == "blue":
self.popover.foreground = ""
else:
self.popover.foreground = "red"

if self.popover.background == "blue":
self.popover.background = "red"
elif self.popover.background == "red":
self.popover.background = ""
else:
self.popover.background = "blue"

self.popover_button.popover("show")
12 changes: 12 additions & 0 deletions client_code/Demo/form_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,19 @@ components:
spacing_above: small
spacing_below: small
visible: true
background: red
foreground: yellow
type: form:MultiSelectDropDown
- event_bindings: {click: change_multi_color}
name: change_multi_color_btn
properties:
text: Change Multi Select Background Color to Blue, Foreground Color to Red
type: Button
- event_bindings: {click: remove_multi_color}
name: change_multi_color_btn
properties:
text: Remove Multi Select Background Color and Foreground Color
type: Button
- layout_properties:
col_widths: {}
grid_position: FBTNBP,PVGRIB
Expand Down
17 changes: 16 additions & 1 deletion client_code/MultiSelectDropDown/Option/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,15 @@ def disabled(self, val):
else:
del self._dom_node.dataset["disabled"]

@property
def foreground(self):
return self._props["foreground"]

@foreground.setter
def foreground(self, value):
self._props["foreground"] = value
self.label.foreground = self.icon_checked.foreground = value

def focus(self):
self._dom_node.focus()

Expand Down Expand Up @@ -137,6 +146,7 @@ def from_dict(cls, item: dict, idx: int) -> tuple:
subtext = item.get("subtext", "")
disabled = not item.get("enabled", True)
key = item.get("key")
foreground = item.get("foreground")

return cls(
idx=idx,
Expand All @@ -146,22 +156,27 @@ def from_dict(cls, item: dict, idx: int) -> tuple:
subtext=subtext,
title=title,
disabled=disabled,
foreground=foreground,
)

@classmethod
def from_items(cls, items):
def from_items(cls, items, foreground=None):
options = []

for idx, item in enumerate(items):
current_foreground = foreground
if isinstance(item, str):
option = cls.from_str(item, idx)
elif isinstance(item, (tuple, list)):
option = cls.from_tuple(item, idx)
elif isinstance(item, dict):
option = cls.from_dict(item, idx)
current_foreground = item.get("foreground", current_foreground)
else:
raise TypeError(f"Invalid item at index {idx} (got type {type(item)})")

option.foreground = current_foreground

options.append(option)

return options
1 change: 1 addition & 0 deletions client_code/MultiSelectDropDown/Option/form_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ properties:
- {default_value: '', important: true, name: subtext, type: string}
- {default_value: false, important: true, name: active, type: boolean}
- {default_value: false, important: true, name: selected, type: boolean}
- {default_value: "", important: true, name: foreground, type: string}
toolbox_item: {hidden: true}
35 changes: 32 additions & 3 deletions client_code/MultiSelectDropDown/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@
"enable_select_all": False,
"width": "",
"visible": True,
"foreground": "",
}


Expand Down Expand Up @@ -196,7 +197,7 @@ def __init__(self, **properties):
self._dd_width = 0
self._dd = DropDown()
self._dd.add_event_handler("change", self._change)
popover(
self.popover = popover(
self._select_btn,
self._dd,
placement="bottom-start",
Expand All @@ -205,11 +206,13 @@ def __init__(self, **properties):
animation=False,
trigger="manual",
max_width="fit-content",
background=self._props["background"],
)

selected = props.pop("selected", ())

self.init_components(**props)

self.set_event_handler("x-popover-init", self._mk_popover)
self.set_event_handler("x-popover-destroy", self._mk_popover)
self._dd.set_event_handler(
Expand All @@ -228,6 +231,33 @@ def format_selected_text(self, count, total):
return ", ".join(opt.title or opt.key for opt in self._options if opt.selected)

##### PROPERTIES #####
@property
def background(self):
return self._props["background"]

@background.setter
def background(self, value):
self._props["background"] = value

_js.get_dom_node(self._select_btn).querySelector("button").style.setProperty(
"background-color", value
)

self.popover.background = value

@property
def foreground(self):
return self._props["foreground"]

@foreground.setter
def foreground(self, value):
self._props["foreground"] = value
_js.get_dom_node(self._select_btn).querySelector("button").style.setProperty(
"color", value
)
for option in self._options:
option.foreground = value

@property
def width(self):
return self._props.get("width")
Expand Down Expand Up @@ -269,8 +299,7 @@ def items(self, value):
self._props["items"] = value
self._close()
selected = self.selected + self._invalid

options = Option.from_items(value)
options = Option.from_items(value, self._props["foreground"])

self._dd.options = self._options = options
self._calc_dd_width()
Expand Down
2 changes: 2 additions & 0 deletions client_code/MultiSelectDropDown/form_template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ properties:
- {default_value: false, group: interaction, important: false, name: enable_select_all, type: boolean}
- {default_value: true, designer_hint: visible, group: appearance, important: true, name: visible, type: boolean}
- {\'fit\' resizes to the selected content: null, default_value: '', description: use css lengths. \'auto\' sets the width as wide as the largest option, group: appearance, name: width, type: string}
- {default_value: "", important: false, type: string, name: background}
- {default_value: "", important: false, type: string, name: foreground}
- default_value: small
group: layout
important: false
Expand Down
28 changes: 27 additions & 1 deletion client_code/popover.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ def __init__(
dismiss_on_scroll=None,
container=None,
arrow=True,
foreground=None,
background=None,
):
_popper_map.set(popper, self)

Expand Down Expand Up @@ -287,6 +289,27 @@ def __init__(
self.make_template()
self.add_behavior()

self.foreground = foreground
self.background = background

@property
def background(self):
return self._background

@background.setter
def background(self, value):
self._background = value
self.dom_popover.style.setProperty("background-color", value)

@property
def foreground(self):
return self._foreground

@foreground.setter
def foreground(self, value):
self._foreground = value
self.dom_popover.style.setProperty("color", value)

def make_template(self):
d = _document.createElement("div")
d.className = "ae-popover"
Expand Down Expand Up @@ -579,6 +602,8 @@ def popover(
dismiss_on_scroll=None,
container=None,
arrow=True,
foreground="",
background="",
):
"""should be called by a button or link
content - either text or an anvil component or Form
Expand Down Expand Up @@ -619,7 +644,7 @@ def popover(
"Support for this may be removed in a future version.",
)

Popover(
return Popover(
self,
content,
title=title,
Expand All @@ -632,6 +657,7 @@ def popover(
dismiss_on_scroll=dismiss_on_scroll,
container=container,
arrow=arrow,
background=background,
)


Expand Down