dash-frontend: Bindings view UX improvements

This commit is contained in:
Aleksander 2026-07-01 22:29:16 +02:00 committed by galister
parent 0962f4c015
commit 4edc6053ce
19 changed files with 185 additions and 47 deletions

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Material Symbols by Google - https://github.com/google/material-design-icons/blob/master/LICENSE --><path fill="#F55" d="m8.4 17l3.6-3.6l3.6 3.6l1.4-1.4l-3.6-3.6L17 8.4L15.6 7L12 10.6L8.4 7L7 8.4l3.6 3.6L7 15.6zm3.6 5q-2.075 0-3.9-.788t-3.175-2.137T2.788 15.9T2 12t.788-3.9t2.137-3.175T8.1 2.788T12 2t3.9.788t3.175 2.137T21.213 8.1T22 12t-.788 3.9t-2.137 3.175t-3.175 2.138T12 22m0-2q3.35 0 5.675-2.325T20 12t-2.325-5.675T12 4T6.325 6.325T4 12t2.325 5.675T12 20m0-8"/></svg>

After

Width:  |  Height:  |  Size: 573 B

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="48"
height="48"
viewBox="0 0 384.00001 383.99998"
version="1.1"
id="svg1"
sodipodi:docname="hand_left.svg"
inkscape:version="1.4.4 (dcaf3e7d9e, 2026-05-05)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:clip-to-page="false"
inkscape:zoom="8"
inkscape:cx="24"
inkscape:cy="15.9375"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<defs
id="defs1" />
<!-- Icon from Phosphor by Phosphor Icons - https://github.com/phosphor-icons/core/blob/main/LICENSE -->
<path
fill="currentColor"
d="m 223.99926,120.14002 v 90.93 c 0,46.2 -36.85,84.55 -83,85.06 a 83.7,83.7 0 0 1 -60.400003,-24.59 c -21.81,-23.07 -46.45,-79.4 -46.45,-79.4 a 16,16 0 0 1 6.53,-22.23 c 7.66,-4 17.1,-0.84 21.4,6.62 l 21,36.44 a 6.09,6.09 0 0 0 6,3.09 h 0.12 a 8.19,8.19 0 0 0 6.800001,-8.18 v -103.74 A 16,16 0 0 1 112.76926,88.140018 c 8.61,0.4 15.23,7.82 15.23,16.430002 v 63.57 a 8,8 0 0 0 8.53,8 8.17,8.17 0 0 0 7.47,-8.25 V 88.140018 a 16,16 0 0 1 16.77,-15.999999 c 8.61,0.4 15.23,7.82 15.23,16.429999 v 87.570002 a 8,8 0 0 0 8.53,8 8.17,8.17 0 0 0 7.47,-8.25 v -55.3 c 0,-8.61 6.62,-16 15.23,-16.43 a 16,16 0 0 1 16.77,15.98"
id="path1" />
<path
fill="currentColor"
d="M 263.19112,258.73409 V 112.03922 h 18.49095 v 130.25847 h 64.10196 v 16.4364 z"
id="text1"
aria-label="L" />
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="48"
height="48"
viewBox="0 0 384 383.99998"
version="1.1"
id="svg1"
sodipodi:docname="hand_right.svg"
inkscape:version="1.4.4 (dcaf3e7d9e, 2026-05-05)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="8"
inkscape:cx="24"
inkscape:cy="15.9375"
inkscape:window-width="1920"
inkscape:window-height="1016"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<defs
id="defs1" />
<!-- Icon from Phosphor by Phosphor Icons - https://github.com/phosphor-icons/core/blob/main/LICENSE -->
<path
fill="currentColor"
d="M 30.079989,119.60999 V 210.54 c 0,46.2 36.85,84.55 83.000011,85.06 a 83.7,83.7 0 0 0 60.4,-24.59 c 21.81,-23.07 46.45,-79.4 46.45,-79.4 a 16,16 0 0 0 -6.53,-22.23 c -7.66,-4.00001 -17.1,-0.84 -21.4,6.62 l -21,36.44 a 6.09,6.09 0 0 1 -6,3.09 h -0.12 a 8.19,8.19 0 0 1 -6.8,-8.18 V 103.60999 a 16,16 0 0 0 -16.77,-16 c -8.61,0.4 -15.23,7.82 -15.23,16.43 V 167.61 a 8,8 0 0 1 -8.53,8 8.17,8.17 0 0 1 -7.47,-8.25 V 87.60999 A 16,16 0 0 0 93.309986,71.609992 c -8.609997,0.4 -15.229997,7.819999 -15.229997,16.429998 V 175.61 a 8,8 0 0 1 -8.53,8 8.17,8.17 0 0 1 -7.47,-8.25 v -55.30001 c 0,-8.61 -6.62,-16 -15.23,-16.43 a 16,16 0 0 0 -16.77,15.98"
id="path1" />
<path
d="m 301.74274,111.50919 q 27.32551,0 40.26918,10.4782 13.14912,10.27275 13.14912,31.22916 0,11.71094 -4.31456,19.51824 -4.31455,7.80729 -11.09457,12.53275 -6.57456,4.52001 -13.97094,7.19093 l 40.26918,65.7456 h -21.57277 l -35.54372,-60.60923 h -29.17461 v 60.60923 H 261.2681 V 111.50919 Z m -1.02728,16.02549 h -20.95641 v 54.44558 h 21.98369 q 17.87458,0 26.09278,-6.98547 8.2182,-7.19092 8.2182,-20.95642 0,-14.38185 -8.62911,-20.34004 -8.62911,-6.16365 -26.70915,-6.16365 z"
id="text1"
fill="currentColor"
aria-label="R" />
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -8,16 +8,16 @@
border_color="#FFFFFF66" border_color="#FFFFFF66"
justify_content="space_between" /> justify_content="space_between" />
<!-- id, text, translation, tooltip --> <!-- id, text, translation, tooltip, min_width -->
<template name="DropdownButton"> <template name="DropdownButton">
<label text="${text}" translation="${translation}" /> <label text="${text}" translation="${translation}" />
<Button id="${id}" height="32" tooltip="${tooltip}" > <Button id="${id}" height="32" tooltip="${tooltip}" >
<div padding_left="8" padding_right="8" min_width="200"> <div padding_left="8" padding_right="8" min_width="${min_width}">
<label id="${id}_value" weight="bold" /> <label id="${id}_value" weight="bold" />
</div> </div>
<div gap="2"> <div gap="2">
<div padding_top="4" padding_bottom="4"> <div padding_top="4" padding_bottom="4">
<rectangle width="2" height="100%" color="#FFFFFF66" /> <rectangle width="2" height="100%" color="#FFFFFF1A" />
</div> </div>
<sprite margin_left="-4" width="30" height="30" color="~color_text" src_builtin="dashboard/down.svg" /> <sprite margin_left="-4" width="30" height="30" color="~color_text" src_builtin="dashboard/down.svg" />
</div> </div>

View File

@ -1,21 +1,30 @@
<layout> <layout>
<include src="../t_group_box.xml" />
<!-- used at runtime [!!!] -->
<include src="../t_dropdown_button.xml" /> <include src="../t_dropdown_button.xml" />
<!-- id, translation --> <!-- id, translation -->
<template name="ActionRow"> <template name="ActionRow">
<div id="${id}" flex_direction="column" gap="4" width="100%" padding="6" round="6" color="#00000044" border="1" border_color="#FFFFFF33"> <rectangle macro="group_box" id="${id}">
<label translation="${translation}" weight="bold" size="14" /> <!-- top row -->
</div> <div flex_direction="row" gap="8" align_items="center">
<sprite src_builtin="dashboard/controller.svg" width="24" height="24"/>
<label translation="${translation}" color="~color_accent" weight="bold" size="14" />
</div>
<!-- filled-in at runtime -->
</rectangle>
</template> </template>
<elements> <elements>
<div flex_direction="column" gap="8" width="100%" align_items="center"> <div flex_direction="column" gap="8" width="100%">
<label id="controller_type" text="OpenXR Bindings" weight="bold" size="18" /> <div flex_direction="column" gap="8" align_items="center" overflow_y="scroll" width="100%" padding="16">
<div id="list_parent" flex_direction="column" gap="6" width="100%"></div> <div id="list_parent" flex_direction="column" gap="6" width="100%"></div>
<div flex_direction="row" gap="4" align_self="end">
<Button id="btn_save" height="32" translation="APP_SETTINGS.SAVE" />
<Button id="btn_cancel" height="32" translation="APP_SETTINGS.CANCEL" />
</div> </div>
<rectangle color="#000000cc" flex_direction="row" gap="8" justify_content="end" padding="8">
<Button id="btn_cancel" sprite_src_builtin="dashboard/cancel.svg" min_width="100" height="32" translation="APP_SETTINGS.CANCEL" />
<Button id="btn_save" sprite_src_builtin="dashboard/check.svg" min_width="100" height="32" translation="APP_SETTINGS.SAVE" />
</rectangle>
</div> </div>
</elements> </elements>
</layout> </layout>

View File

@ -41,7 +41,8 @@
gradient="vertical" gradient="vertical"
position="relative" position="relative"
> >
<div id="content" padding="16" width="100%" height="100%" position="absolute" overflow_y="scroll"> <div id="content" width="100%" height="100%" position="absolute" overflow_y="scroll">
<!-- Padding set at runtime -->
<!-- Content, filled-in at runtime --> <!-- Content, filled-in at runtime -->
</div> </div>
</rectangle> </rectangle>

View File

@ -80,12 +80,18 @@ fn create_input_profiles_button(
impl State { impl State {
pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> { pub fn mount(par: SettingsMountParams) -> anyhow::Result<State> {
let tasks = Tasks::<Task>::new();
let popup = PopupHolder::<input_profiles::View>::default();
let c = options_category( let c = options_category(
par.mp, par.mp,
par.id_parent, par.id_parent,
"APP_SETTINGS.CONTROLS", "APP_SETTINGS.CONTROLS",
"dashboard/controller.svg", "dashboard/controller.svg",
)?; )?;
if par.feats.openxr {
create_input_profiles_button(par.mp, c, tasks.clone(), &popup)?;
}
options_dropdown::<wlx_common::config::AltModifier>(par.mp, c, &SettingType::KeyboardMiddleClick)?; options_dropdown::<wlx_common::config::AltModifier>(par.mp, c, &SettingType::KeyboardMiddleClick)?;
options_dropdown::<wlx_common::config::HandsfreePointer>(par.mp, c, &SettingType::HandsfreePointer)?; options_dropdown::<wlx_common::config::HandsfreePointer>(par.mp, c, &SettingType::HandsfreePointer)?;
options_checkbox(par.mp, c, SettingType::FocusFollowsMouseMode)?; options_checkbox(par.mp, c, SettingType::FocusFollowsMouseMode)?;
@ -111,13 +117,6 @@ impl State {
options_slider_i32(par.mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50)?; options_slider_i32(par.mp, c, SettingType::ClickFreezeTimeMs, 0, 500, 50)?;
let tasks = Tasks::<Task>::new();
let popup = PopupHolder::<input_profiles::View>::default();
if par.feats.openxr {
create_input_profiles_button(par.mp, c, tasks.clone(), &popup)?;
}
Ok(State { Ok(State {
popup_input_profiles: popup, popup_input_profiles: popup,
frontend_tasks: par.frontend_tasks.clone(), frontend_tasks: par.frontend_tasks.clone(),

View File

@ -6,11 +6,12 @@ use std::{
use wgui::{ use wgui::{
assets::AssetPath, assets::AssetPath,
components::button::ComponentButton, components::button::ComponentButton,
event::EventAlterables, event::{EventAlterables, StyleSetRequest},
globals::WguiGlobals, globals::WguiGlobals,
i18n::Translation, i18n::Translation,
layout::{Layout, LayoutTask, LayoutTasks, WidgetID}, layout::{Layout, LayoutTask, LayoutTasks, WidgetID},
parser::{Fetchable, ParseDocumentParams, ParserState}, parser::{Fetchable, ParseDocumentParams, ParserState},
taffy::Rect,
widget::label::WidgetLabel, widget::label::WidgetLabel,
}; };
use wlx_common::config::GeneralConfig; use wlx_common::config::GeneralConfig;
@ -187,19 +188,33 @@ pub struct PopupContentFuncData<'a> {
type PopupClosedCallback = Box<dyn FnOnce()>; type PopupClosedCallback = Box<dyn FnOnce()>;
type OnContentCallback = Box<dyn FnOnce(PopupContentFuncData) -> anyhow::Result<PopupClosedCallback>>; type OnContentCallback = Box<dyn FnOnce(PopupContentFuncData) -> anyhow::Result<PopupClosedCallback>>;
#[derive(Clone, Default)]
pub enum PopupPadding {
#[default]
Normal,
None,
}
#[derive(Default, Clone)]
pub struct MountPopupOnceParamsExtra {
pub padding: PopupPadding,
}
// we need to implement Clone here, but the underlying function can be called only once. // we need to implement Clone here, but the underlying function can be called only once.
// on_content will be cleared after the first call // on_content will be cleared after the first call
#[derive(Clone)] #[derive(Clone)]
pub struct MountPopupOnceParams { pub struct MountPopupOnceParams {
title: Translation, title: Translation,
on_content: Rc<RefCell<Option<OnContentCallback>>>, on_content: Rc<RefCell<Option<OnContentCallback>>>,
extra: MountPopupOnceParamsExtra,
} }
impl MountPopupOnceParams { impl MountPopupOnceParams {
pub fn new(title: Translation, on_content: OnContentCallback) -> Self { pub fn new(title: Translation, on_content: OnContentCallback, extra: MountPopupOnceParamsExtra) -> Self {
Self { Self {
title, title,
on_content: Rc::new(RefCell::new(Some(on_content))), on_content: Rc::new(RefCell::new(Some(on_content))),
extra,
} }
} }
} }
@ -257,6 +272,7 @@ impl PopupManager {
layout: &mut Layout, layout: &mut Layout,
frontend_tasks: &FrontendTasks, frontend_tasks: &FrontendTasks,
popup_title: &Translation, popup_title: &Translation,
popup_padding: PopupPadding,
) -> anyhow::Result<(PopupHandle, WidgetID /* content widget ID */)> { ) -> anyhow::Result<(PopupHandle, WidgetID /* content widget ID */)> {
let doc_params = &ParseDocumentParams { let doc_params = &ParseDocumentParams {
globals: globals.clone(), globals: globals.clone(),
@ -268,6 +284,16 @@ impl PopupManager {
let id_root = state.get_widget_id("root")?; let id_root = state.get_widget_id("root")?;
let id_content = state.get_widget_id("content")?; let id_content = state.get_widget_id("content")?;
let padding = match popup_padding {
PopupPadding::Normal => 16.0,
PopupPadding::None => 0.0,
};
layout.tasks.push(LayoutTask::SetWidgetStyle(
id_content,
StyleSetRequest::Padding(Rect::length(padding)),
));
{ {
let mut label_title = state.fetch_widget_as::<WidgetLabel>(&layout.state, "popup_title")?; let mut label_title = state.fetch_widget_as::<WidgetLabel>(&layout.state, "popup_title")?;
label_title.set_text_simple(&mut globals.get(), popup_title.clone()); label_title.set_text_simple(&mut globals.get(), popup_title.clone());
@ -330,7 +356,8 @@ impl PopupManager {
anyhow::bail!("mount_popup_once called more than once"); anyhow::bail!("mount_popup_once called more than once");
}; };
let (popup_handle, id_content) = self.mount_popup_prepare(globals, layout, frontend_tasks, &params.title)?; let (popup_handle, id_content) =
self.mount_popup_prepare(globals, layout, frontend_tasks, &params.title, params.extra.padding)?;
// mount user-set popup content // mount user-set popup content
let closed_callback = on_content_func(PopupContentFuncData { let closed_callback = on_content_func(PopupContentFuncData {

View File

@ -453,5 +453,6 @@ pub fn mount_popup(frontend_tasks: FrontendTasks, globals: WguiGlobals, entry: D
popup.set_view(data.handle, view, None); popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout)) Ok(popup.get_close_callback(data.layout))
}), }),
Default::default(), /* extra */
))); )));
} }

View File

@ -1,5 +1,6 @@
use std::{borrow::Cow, collections::HashMap, rc::Rc}; use std::{borrow::Cow, collections::HashMap, rc::Rc};
use glam::Vec2;
use wgui::{ use wgui::{
assets::AssetPath, assets::AssetPath,
components::button::{ButtonClickEvent, ComponentButton}, components::button::{ButtonClickEvent, ComponentButton},
@ -22,7 +23,8 @@ use crate::{
tab::settings::horiz_cell, tab::settings::horiz_cell,
util::{ util::{
openxr_bindings_schema::{ClickType, Component, IdentifierType, ParsedOpenXrInputPath, Profile, Side}, openxr_bindings_schema::{ClickType, Component, IdentifierType, ParsedOpenXrInputPath, Profile, Side},
popup_manager::{MountPopupOnceParams, PopupHolder}, popup_manager::{MountPopupOnceParams, MountPopupOnceParamsExtra, PopupHolder, PopupPadding},
wgui_simple,
}, },
views::{ViewTrait, ViewUpdateParams}, views::{ViewTrait, ViewUpdateParams},
}; };
@ -85,7 +87,7 @@ impl ViewTrait for View {
} }
// Dropdown handling // Dropdown handling
if let TickResult::Action(name) = self.context_menu.tick(&mut par.layout, &mut self.parser_state)? if let TickResult::Action(name) = self.context_menu.tick(par.layout, &mut self.parser_state)?
&& let (Some(action), Some(_), Some(action_name), Some(side), Some(value)) = { && let (Some(action), Some(_), Some(action_name), Some(side), Some(value)) = {
let mut s = name.splitn(5, ';'); let mut s = name.splitn(5, ';');
(s.next(), s.next(), s.next(), s.next(), s.next()) (s.next(), s.next(), s.next(), s.next(), s.next())
@ -95,8 +97,8 @@ impl ViewTrait for View {
log::warn!("{action_name}"); log::warn!("{action_name}");
let mut cur_profile = &mut self.profiles[self.cur_profile_idx]; let cur_profile = &mut self.profiles[self.cur_profile_idx];
let action_mut = get_action_mut(&mut cur_profile, action_name); let action_mut = get_action_mut(cur_profile, action_name);
let side_mut = if side == "right" { let side_mut = if side == "right" {
&mut action_mut.right &mut action_mut.right
} else { } else {
@ -163,14 +165,6 @@ impl View {
let list_parent = parser_state.fetch_widget(&params.layout.state, "list_parent")?.id; let list_parent = parser_state.fetch_widget(&params.layout.state, "list_parent")?.id;
let tasks = Tasks::new(); let tasks = Tasks::new();
{
let mut title_label = parser_state.fetch_widget_as::<WidgetLabel>(&params.layout.state, "controller_type")?;
title_label.set_text_simple(
&mut params.globals.get(),
Translation::from_raw_text_rc(params.profile.title.clone()),
);
}
tasks.handle_button( tasks.handle_button(
&parser_state.fetch_component_as::<ComponentButton>("btn_save")?, &parser_state.fetch_component_as::<ComponentButton>("btn_save")?,
Task::Save, Task::Save,
@ -267,7 +261,7 @@ pub fn mount_popup(
frontend_tasks frontend_tasks
.clone() .clone()
.push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new( .push(FrontendTask::MountPopupOnce(MountPopupOnceParams::new(
Translation::from_translation_key("APP_SETTINGS.INPUT_PROFILES"), Translation::from_raw_text_rc(profile.title.clone()),
Box::new(move |data| { Box::new(move |data| {
let close_callback = popup.get_close_callback(data.layout); let close_callback = popup.get_close_callback(data.layout);
let view = View::new(Params { let view = View::new(Params {
@ -282,6 +276,9 @@ pub fn mount_popup(
popup.set_view(data.handle, view, None); popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout)) Ok(popup.get_close_callback(data.layout))
}), }),
MountPopupOnceParamsExtra {
padding: PopupPadding::None,
},
))); )));
} }
@ -367,16 +364,13 @@ fn input_controls_for_hand(
return Ok(()); // skip return Ok(()); // skip
} }
let current = current let current = current.and_then(|cur| ParsedOpenXrInputPath::try_from(cur).log_warn(cur).ok());
.map(|cur| ParsedOpenXrInputPath::try_from(cur).log_warn(cur).ok())
.flatten();
let parent = horiz_cell(mp.layout, parent)?; let parent = horiz_cell(mp.layout, parent)?;
let available_components = current let available_components = current
.as_ref() .as_ref()
.map(|par| profile.subpaths.get(&par.to_subpath())) .and_then(|par| profile.subpaths.get(&par.to_subpath()))
.flatten()
.map(|subp| subp.get_effective_components()) .map(|subp| subp.get_effective_components())
.unwrap_or_default(); .unwrap_or_default();
@ -387,8 +381,7 @@ fn input_controls_for_hand(
.filter_map(|(key, _)| { .filter_map(|(key, _)| {
key key
.strip_prefix("/input/") .strip_prefix("/input/")
.map(|ident| IdentifierType::try_from(ident).ok()) .and_then(|ident| IdentifierType::try_from(ident).ok())
.flatten()
}) })
.collect::<Rc<[IdentifierType]>>(); .collect::<Rc<[IdentifierType]>>();
@ -430,11 +423,16 @@ fn subpath_dropdown(
let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new(); let mut params: HashMap<Rc<str>, Rc<str>> = HashMap::new();
params.insert(Rc::from("id"), Rc::from(id.as_ref())); params.insert(Rc::from("id"), Rc::from(id.as_ref()));
params.insert(
Rc::from("translation"),
Rc::from(format!("APP_SETTINGS.BINDINGS.{}", side.as_ref().to_uppercase())),
);
params.insert(Rc::from("tooltip"), Rc::from("APP_SETTINGS.BINDINGS.SUBPATH")); params.insert(Rc::from("tooltip"), Rc::from("APP_SETTINGS.BINDINGS.SUBPATH"));
params.insert(Rc::from("min_width"), Rc::from("100"));
// left/right hand icon
wgui_simple::create_icon(
mp.layout,
parent,
Vec2::new(32.0, 32.0),
AssetPath::BuiltIn(&format!("dashboard/hand_{}.svg", side.as_ref().to_lowercase())),
)?;
mp.parser_state mp.parser_state
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?; .instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;
@ -508,6 +506,7 @@ fn component_dropdown(
params.insert(Rc::from("id"), Rc::from(id.as_ref())); params.insert(Rc::from("id"), Rc::from(id.as_ref()));
params.insert(Rc::from("text"), Rc::from("")); params.insert(Rc::from("text"), Rc::from(""));
params.insert(Rc::from("tooltip"), Rc::from("APP_SETTINGS.BINDINGS.COMPONENT")); params.insert(Rc::from("tooltip"), Rc::from("APP_SETTINGS.BINDINGS.COMPONENT"));
params.insert(Rc::from("min_width"), Rc::from("100"));
mp.parser_state mp.parser_state
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?; .instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;
@ -561,6 +560,7 @@ fn clicks_dropdown(mp: &mut MacroParams, parent: WidgetID, action: Rc<str>, curr
params.insert(Rc::from("id"), Rc::from(id.as_ref())); params.insert(Rc::from("id"), Rc::from(id.as_ref()));
params.insert(Rc::from("text"), Rc::from("")); params.insert(Rc::from("text"), Rc::from(""));
params.insert(Rc::from("tooltip"), Rc::from("APP_SETTINGS.BINDINGS.CLICK.TYPE")); params.insert(Rc::from("tooltip"), Rc::from("APP_SETTINGS.BINDINGS.CLICK.TYPE"));
params.insert(Rc::from("min_width"), Rc::from("100"));
mp.parser_state mp.parser_state
.instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?; .instantiate_template(mp.doc_params, "DropdownButton", mp.layout, parent, params)?;

View File

@ -123,5 +123,6 @@ pub fn mount_popup(popup: PopupHolder<View>, frontend_tasks: FrontendTasks, para
popup.set_view(data.handle, view, None); popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout)) Ok(popup.get_close_callback(data.layout))
}), }),
Default::default(), /* extra */
))); )));
} }

View File

@ -261,5 +261,6 @@ pub fn mount_popup(
popup.set_view(data.handle, view, Some(on_view_close)); popup.set_view(data.handle, view, Some(on_view_close));
Ok(popup.get_close_callback(data.layout)) Ok(popup.get_close_callback(data.layout))
}), }),
Default::default(), /* extra */
))); )));
} }

View File

@ -224,5 +224,6 @@ pub fn mount_popup(
popup.set_view(data.handle, view, None); popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout)) Ok(popup.get_close_callback(data.layout))
}), }),
Default::default(), /* extra */
))); )));
} }

View File

@ -136,5 +136,6 @@ pub fn mount_popup(frontend_tasks: FrontendTasks, globals: WguiGlobals, popup: P
popup.set_view(data.handle, view, None); popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout)) Ok(popup.get_close_callback(data.layout))
}), }),
Default::default(), /* extra */
))); )));
} }

View File

@ -393,5 +393,6 @@ pub fn mount_popup(
popup.set_view(data.handle, view, None); popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout)) Ok(popup.get_close_callback(data.layout))
}), }),
Default::default(), /* extra */
))); )));
} }

View File

@ -297,5 +297,6 @@ pub fn mount_popup(
popup.set_view(data.handle, view, None); popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout)) Ok(popup.get_close_callback(data.layout))
}), }),
Default::default(), /* extra */
))); )));
} }

View File

@ -265,5 +265,6 @@ pub fn mount_popup(frontend_tasks: FrontendTasks, globals: WguiGlobals, popup: P
popup.set_view(data.handle, view, None); popup.set_view(data.handle, view, None);
Ok(popup.get_close_callback(data.layout)) Ok(popup.get_close_callback(data.layout))
}), }),
Default::default(), /* extra */
))); )));
} }

View File

@ -107,6 +107,7 @@ impl Event {
pub enum StyleSetRequest { pub enum StyleSetRequest {
Display(taffy::Display), Display(taffy::Display),
Margin(taffy::Rect<taffy::LengthPercentageAuto>), Margin(taffy::Rect<taffy::LengthPercentageAuto>),
Padding(taffy::Rect<taffy::LengthPercentage>),
Width(taffy::Dimension), Width(taffy::Dimension),
Height(taffy::Dimension), Height(taffy::Dimension),
Size(taffy::Size<taffy::Dimension>), Size(taffy::Size<taffy::Dimension>),

View File

@ -817,6 +817,9 @@ impl Layout {
event::StyleSetRequest::Margin(margin) => { event::StyleSetRequest::Margin(margin) => {
cur_style.margin = *margin; cur_style.margin = *margin;
} }
event::StyleSetRequest::Padding(padding) => {
cur_style.padding = *padding;
}
event::StyleSetRequest::Width(val) => { event::StyleSetRequest::Width(val) => {
cur_style.size.width = *val; cur_style.size.width = *val;
} }