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

add a fullscreen parameter to display bigger menu in map applications #756

Merged
merged 8 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from 6 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
7 changes: 7 additions & 0 deletions sepal_ui/frontend/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ header.v-app-bar {
/* set the menu_content on top of the map when it's set to fullscreen */
.v-menu__content {
z-index: 802 !important;
max-width: 100% !important;
}

/* make sure the dialog remain on top of the bars (header and footer) */
Expand Down Expand Up @@ -103,3 +104,9 @@ nav.v-navigation-drawer {
border-top-left-radius: 0;
border-top-right-radius: 0;
}

/* css rules for fullscreen menus */
.v-card.v-menu-fullscreen {
width: calc(100vw - 80px);
height: calc(100vh - 20px);
}
33 changes: 29 additions & 4 deletions sepal_ui/mapping/menu_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

import ipyvuetify as v
from ipyleaflet import Map, WidgetControl
from traitlets import Int
from traitlets import Bool, Int
from typing_extensions import Self

from sepal_ui import color
from sepal_ui import sepalwidgets as sw
from sepal_ui.mapping.map_btn import MapBtn

Expand All @@ -24,14 +25,18 @@ class MenuControl(WidgetControl):
group: Int = Int().tag(sync=True)
"The group of Menu control, tell how the Menucontrol interact with the others"

fullscreen: Bool(False).tag(sync=True)
"Either or not the Menu container should be displayed in fullscreen on top of the map"

def __init__(
self,
icon_content: str,
card_content: Union[v.VuetifyWidget, str],
card_title: str = "",
m: Optional[Map] = None,
group: int = 0,
**kwargs
fullscreen: bool = False,
**kwargs,
) -> None:
"""
Widget control displaying a btn on the map.
Expand All @@ -45,12 +50,14 @@ def __init__(
card_title: the card title. THe tile title will override this parameter if existing
m: The map associated with the Menu
group: The group of Menu control, tell how the Menucontrol interact with the others
fullscreen: Either or not the Menu container should be displayed in fullscreen on top of the map
"""
# save the map in the members
self.m = m

# set the menucontrol group
# set the menucontrol parameters
self.group = group
self.fullscreen = fullscreen

# create a clickable btn
btn = MapBtn(content=icon_content, v_on="menu.on")
Expand All @@ -77,11 +84,11 @@ def __init__(
style_="overflow: auto",
children=children,
)
not fullscreen or card.class_list.add("v-menu-fullscreen")

# assemble everything in a menu
self.menu = sw.Menu(
v_model=False,
close_on_click=False,
close_on_content_click=False,
children=[card],
v_slots=[slot],
Expand All @@ -101,6 +108,7 @@ def __init__(
# add some interaction
self.observe(self.update_position, "position")
self.menu.observe(self.close_others, "v_model")
self.menu.observe(self.activate, "v_model")

def update_position(self, *args) -> None:
"""
Expand All @@ -123,6 +131,8 @@ def set_size(
"""
Set the size of the card using all the sizing parameters from a v.Card.

Default to None for everything if the menu control is fullscreened to avoid css conflict.

Args:
min_width: a fully qualified css description of the wanted min_width. default to 400px.
max_width: a fully qualified css description of the wanted max_width. default to 400px.
Expand All @@ -131,6 +141,10 @@ def set_size(
"""
card = self.menu.children[0]

# special case to None for everything if the menu is displayed in fullscree
if self.fullscreen:
min_width = max_width = min_height = max_height = None

card.min_width = min_width
card.max_width = max_width
card.min_height = min_height
Expand Down Expand Up @@ -158,3 +172,14 @@ def close_others(self, *args) -> None:
]

return

def activate(self, *args) -> None:
"""
Change the background color of the btn with respect to the status.
"""
# grey is contrasted enought for both ligh and dark theme
# could be customized further if requested
bg_color = "gray" if self.menu.v_model is True else color.bg
self.menu.v_slots[0]["children"].style_ = f"background: {bg_color};"

return
49 changes: 46 additions & 3 deletions tests/test_MenuControl.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from sepal_ui import color
from sepal_ui import mapping as sm
from sepal_ui import sepalwidgets as sw


class TestMenuControl:
def test_init(self):
def test_init(self) -> None:
"""Init a menu control in different setup"""

# create a tile
tile = sw.Tile(
Expand Down Expand Up @@ -32,7 +34,8 @@ def test_init(self):

return

def test_update_position(self):
def test_update_position(self) -> None:
"""Check that the position can be updated dynamically"""

# create the widget
menu_control = sm.MenuControl("fa-solid fa-folder", sw.Card())
Expand All @@ -52,7 +55,8 @@ def test_update_position(self):

return

def test_close_others(self):
def test_close_others(self) -> None:
"""Check that opening a menu is closing the others"""

# add controls on the map
m = sm.SepalMap()
Expand Down Expand Up @@ -95,3 +99,42 @@ def test_close_others(self):
assert control_4.menu.v_model is True

return

def test_fullscreen(self) -> None:
"""Check if the fullscreen display of a menu"""

# create the menu_control
tile = sw.Tile("toto", "tutu", inputs=[sw.Slider()])
m = sm.SepalMap()
tile_control = sm.MenuControl("tutu", tile, fullscreen=True)
m.add(tile_control)

# check the class as it's the only thing that changes
card = tile_control.menu.children[0]
assert "v-menu-fullscreen" in card.class_
assert card.min_width is None
assert card.max_width is None
assert card.min_height is None
assert card.max_height is None

return

def test_activate(self) -> None:
"""check that activating the menu changes the color of the button"""

# create the menu_control
tile = sw.Tile("toto", "tutu", inputs=[sw.Slider()])
m = sm.SepalMap()
tile_control = sm.MenuControl("tutu", tile, fullscreen=True)
m.add(tile_control)

# use a variable that point to the btn style
btn = tile_control.menu.v_slots[0]["children"]

# open the controle
tile_control.menu.v_model = True
assert btn.style_ == "background: gray;"

# close the controle
tile_control.menu.v_model = False
assert btn.style_ == f"background: {color.bg};"