mirror of https://github.com/wayvr-org/wayvr.git
wgui: Add `ColorSelector` component
This commit is contained in:
parent
5eb258e310
commit
0c1b0906c1
|
|
@ -485,7 +485,6 @@ impl<T: 'static> Frontend<T> {
|
|||
|
||||
fn action_show_audio_settings(&mut self) -> anyhow::Result<()> {
|
||||
self.window_audio_settings.open(&mut WguiWindowParams {
|
||||
globals: &self.globals,
|
||||
position: Vec2::new(64.0, 64.0),
|
||||
layout: &mut self.layout,
|
||||
extra: WguiWindowParamsExtra {
|
||||
|
|
|
|||
|
|
@ -267,7 +267,6 @@ impl SubtabGeneralSettings {
|
|||
let tasks = tasks.clone();
|
||||
Box::new(move |_common, e| {
|
||||
tasks.push(Task::SetBrightness(e.value / 100.0));
|
||||
Ok(())
|
||||
})
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ pub fn options_slider_f32(
|
|||
let tasks = mp.tasks.clone();
|
||||
move |_common, e| {
|
||||
tasks.push(Task::UpdateFloat(setting, e.value));
|
||||
Ok(())
|
||||
}
|
||||
}));
|
||||
|
||||
|
|
@ -168,7 +167,6 @@ pub fn options_slider_i32(
|
|||
let tasks = mp.tasks.clone();
|
||||
move |_common, e| {
|
||||
tasks.push(Task::UpdateInt(setting, e.value as i32));
|
||||
Ok(())
|
||||
}
|
||||
}));
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -823,8 +823,10 @@ impl View {
|
|||
slider.on_value_changed({
|
||||
let control = params.control.clone();
|
||||
Box::new(move |_common, event| {
|
||||
control.on_volume_change(event.value * VOLUME_MULT)?;
|
||||
Ok(())
|
||||
if let Err(e) = control.on_volume_change(event.value * VOLUME_MULT) {
|
||||
log::error!("{:?}", e);
|
||||
debug_assert!(false);
|
||||
};
|
||||
})
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -92,4 +92,4 @@
|
|||
</div>
|
||||
</rectangle>
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
|
|
|
|||
|
|
@ -59,7 +59,11 @@
|
|||
</div>
|
||||
</rectangle>
|
||||
|
||||
<div>
|
||||
<div gap="4" flex_direction="column">
|
||||
<rectangle macro="rect">
|
||||
<label text="Color selector!"/>
|
||||
<ColorSelector />
|
||||
</rectangle>
|
||||
<rectangle macro="rect">
|
||||
<label text="Context menu test" />
|
||||
<Button id="button_context_menu" text="Show context menu" />
|
||||
|
|
@ -121,4 +125,4 @@
|
|||
</rectangle>
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
</layout>
|
||||
|
|
|
|||
|
|
@ -229,7 +229,6 @@ impl TestbedGeneric {
|
|||
data: &mut Data,
|
||||
) -> anyhow::Result<()> {
|
||||
data.popup_window.open(&mut WguiWindowParams {
|
||||
globals: &self.globals,
|
||||
position: Vec2::new(128.0, 128.0),
|
||||
layout: &mut self.layout,
|
||||
extra: WguiWindowParamsExtra {
|
||||
|
|
|
|||
|
|
@ -674,7 +674,6 @@ fn set_up_slider(
|
|||
OverlaySelector::Id(*overlay_id.borrow()),
|
||||
Box::new(move |app, owc| callback(app, owc, e_value)),
|
||||
)));
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
<layout>
|
||||
<macro name="slider" min_value="0" max_value="255" width="200" height="24" />
|
||||
<macro name="color_pip" width="16" height="16" round="100%" />
|
||||
<macro name="slider_flow" align_items="center" gap="8" />
|
||||
|
||||
<elements>
|
||||
<div gap="8" align_items="center">
|
||||
<div gap="8" flex_direction="column">
|
||||
<div macro="slider_flow">
|
||||
<rectangle macro="color_pip" color="#FF0000"/>
|
||||
<Slider id="slider_r" macro="slider" />
|
||||
</div>
|
||||
<div macro="slider_flow">
|
||||
<rectangle macro="color_pip" color="#00FF00"/>
|
||||
<Slider id="slider_g" macro="slider" />
|
||||
</div>
|
||||
<div macro="slider_flow">
|
||||
<rectangle macro="color_pip" color="#0000FF"/>
|
||||
<Slider id="slider_b" macro="slider" />
|
||||
</div>
|
||||
</div>
|
||||
<rectangle id="rect_color" width="96" height="96" border="4" color="#ffffff" border_color="#000000" round="4" />
|
||||
</div>
|
||||
</elements>
|
||||
</layout>
|
||||
|
|
@ -70,7 +70,11 @@ impl ComponentTrait for ComponentBarGraph {
|
|||
|
||||
fn refresh(&self, data: &mut RefreshData) {
|
||||
let state = self.state.borrow();
|
||||
self.update_limits_text(&state, data.common);
|
||||
|
||||
// FIXME: refactor this after merging feat-skybox-catalog branch
|
||||
let mut lc = data.layout.start_common();
|
||||
self.update_limits_text(&state, &mut lc.common());
|
||||
let _ = lc.finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -123,15 +123,21 @@ impl ComponentTrait for ComponentButton {
|
|||
fn refresh(&self, data: &mut RefreshData) {
|
||||
let mut state = self.state.borrow_mut();
|
||||
|
||||
// FIXME: refactor this after merging feat-skybox-catalog branch
|
||||
let mut lc = data.layout.start_common();
|
||||
|
||||
if state.active_tooltip.is_some() {
|
||||
if let Some(node_id) = data.common.state.nodes.get(self.base.get_id()) {
|
||||
if !widget::is_node_visible(&data.common.state.tree, *node_id) {
|
||||
let common = lc.common();
|
||||
if let Some(node_id) = common.state.nodes.get(self.base.get_id()) {
|
||||
if !widget::is_node_visible(&common.state.tree, *node_id) {
|
||||
state.active_tooltip = None; // destroy the tooltip, this button is now hidden
|
||||
}
|
||||
} else {
|
||||
debug_assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
let _ = lc.finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -139,6 +145,10 @@ fn get_color2(color: &drawing::Color, gradient_intensity: f32) -> drawing::Color
|
|||
color.lerp(&Color::new(0.0, 0.0, 0.0, color.a), gradient_intensity)
|
||||
}
|
||||
|
||||
fn get_hover_color(color: &drawing::Color) -> drawing::Color {
|
||||
Color::new(color.r + 0.25, color.g + 0.25, color.g + 0.25, color.a + 0.15)
|
||||
}
|
||||
|
||||
impl ComponentButton {
|
||||
pub fn get_label(&self) -> WidgetID {
|
||||
self.data.id_label
|
||||
|
|
@ -165,7 +175,7 @@ impl ComponentButton {
|
|||
|
||||
let mut state = self.state.borrow_mut();
|
||||
state.colors.color = color;
|
||||
|
||||
state.colors.hover_color = get_hover_color(&color);
|
||||
rect.params.color = color;
|
||||
rect.params.color2 = get_color2(&color, gradient_intensity);
|
||||
}
|
||||
|
|
@ -435,9 +445,7 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
|||
.border_color
|
||||
.unwrap_or_else(|| Color::new(color.r, color.g, color.b, color.a + 0.25));
|
||||
|
||||
let hover_color = params
|
||||
.hover_color
|
||||
.unwrap_or_else(|| Color::new(color.r + 0.25, color.g + 0.25, color.g + 0.25, color.a + 0.15));
|
||||
let hover_color = params.hover_color.unwrap_or_else(|| get_hover_color(&color));
|
||||
|
||||
let hover_border_color = params
|
||||
.hover_border_color
|
||||
|
|
|
|||
|
|
@ -0,0 +1,299 @@
|
|||
use crate::{
|
||||
assets::AssetPath,
|
||||
components::{
|
||||
Component, ComponentBase, ComponentTrait, RefreshData,
|
||||
button::{self, ComponentButton},
|
||||
slider::{ComponentSlider, SliderValueChangedCallback},
|
||||
},
|
||||
drawing::{self},
|
||||
event::CallbackDataCommon,
|
||||
globals::WguiGlobals,
|
||||
i18n::Translation,
|
||||
layout::{Layout, WidgetID, WidgetPair},
|
||||
parser::{self, Fetchable, ParseDocumentParams, ParserState},
|
||||
widget::{ConstructEssentials, rectangle::WidgetRectangle, util::WLength},
|
||||
windowing::window::{WguiWindow, WguiWindowParams, WguiWindowParamsExtra},
|
||||
};
|
||||
use glam::Vec2;
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
rc::{Rc, Weak},
|
||||
};
|
||||
use taffy::prelude::length;
|
||||
|
||||
pub struct Params {
|
||||
pub color: drawing::Color,
|
||||
pub style: taffy::Style,
|
||||
}
|
||||
|
||||
impl Default for Params {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
color: drawing::Color::new(1.0, 1.0, 1.0, 1.0),
|
||||
style: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WantsOpen {
|
||||
position: Vec2,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
struct PopupState {
|
||||
slider_r: Rc<ComponentSlider>,
|
||||
slider_g: Rc<ComponentSlider>,
|
||||
slider_b: Rc<ComponentSlider>,
|
||||
id_rect_color: WidgetID,
|
||||
}
|
||||
|
||||
struct State {
|
||||
color: drawing::Color,
|
||||
self_ref: Weak<ComponentColorSelector>,
|
||||
wants_open: Option<WantsOpen>,
|
||||
on_changed: Option<ColorSelectorChangedCallback>,
|
||||
popup_state: Option<PopupState>,
|
||||
}
|
||||
|
||||
struct Data {
|
||||
button: Rc<ComponentButton>,
|
||||
}
|
||||
|
||||
pub struct ColorSelectorChangedEvent {
|
||||
pub color: drawing::Color,
|
||||
}
|
||||
|
||||
pub type ColorSelectorChangedCallback = Box<dyn Fn(&mut CallbackDataCommon, ColorSelectorChangedEvent)>;
|
||||
|
||||
pub struct ComponentColorSelector {
|
||||
base: ComponentBase,
|
||||
data: Rc<Data>,
|
||||
state: Rc<RefCell<State>>,
|
||||
window: WguiWindow,
|
||||
}
|
||||
|
||||
impl ComponentTrait for ComponentColorSelector {
|
||||
fn base(&self) -> &ComponentBase {
|
||||
&self.base
|
||||
}
|
||||
|
||||
fn base_mut(&mut self) -> &mut ComponentBase {
|
||||
&mut self.base
|
||||
}
|
||||
|
||||
fn refresh(&self, data: &mut RefreshData) {
|
||||
let mut state = self.state.borrow_mut();
|
||||
|
||||
if let Some(wants_open) = state.wants_open.take() {
|
||||
if let Err(e) = self.open(data.layout, &mut state, wants_open.position) {
|
||||
log::error!("{:?}", e);
|
||||
debug_assert!(false);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: refactor this after merging feat-skybox-catalog branch
|
||||
let mut lc = data.layout.start_common();
|
||||
let mut common = lc.common();
|
||||
|
||||
self.data.button.set_text(
|
||||
&mut common,
|
||||
Translation::from_raw_text_string(format!("{}", state.color.to_hex_rgb())),
|
||||
);
|
||||
|
||||
self.data.button.set_color(&mut common, state.color);
|
||||
|
||||
let _ = lc.finish();
|
||||
}
|
||||
}
|
||||
|
||||
enum ColorIndex {
|
||||
Red,
|
||||
Green,
|
||||
Blue,
|
||||
}
|
||||
|
||||
fn set_color_internal(state: &mut State, common: &mut CallbackDataCommon, color: drawing::Color) {
|
||||
if state.color == color {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(on_changed) = &state.on_changed {
|
||||
on_changed(common, ColorSelectorChangedEvent { color })
|
||||
}
|
||||
|
||||
state.color = color;
|
||||
common.alterables.refresh_component_once(&state.self_ref);
|
||||
common.alterables.mark_redraw();
|
||||
}
|
||||
|
||||
impl ComponentColorSelector {
|
||||
pub fn on_changed(&self, func: ColorSelectorChangedCallback) {
|
||||
self.state.borrow_mut().on_changed = Some(func);
|
||||
}
|
||||
|
||||
pub fn set_color(&self, common: &mut CallbackDataCommon, color: drawing::Color) {
|
||||
let mut state = self.state.borrow_mut();
|
||||
set_color_internal(&mut state, common, color);
|
||||
}
|
||||
|
||||
pub fn get_color(&self) -> drawing::Color {
|
||||
self.state.borrow().color
|
||||
}
|
||||
|
||||
fn open(&self, layout: &mut Layout, state: &mut State, position: Vec2) -> anyhow::Result<()> {
|
||||
self.window.open(&mut WguiWindowParams {
|
||||
position,
|
||||
layout,
|
||||
extra: WguiWindowParamsExtra {
|
||||
close_if_clicked_outside: true,
|
||||
// TODO: translation text in wgui too?
|
||||
title: Some(Translation::from_raw_text("Select color")),
|
||||
..Default::default()
|
||||
},
|
||||
})?;
|
||||
|
||||
let id_content = self.window.get_content().id;
|
||||
|
||||
let parser_state = parser::parse_from_assets(
|
||||
&mut ParseDocumentParams {
|
||||
globals: layout.state.globals.clone(),
|
||||
path: AssetPath::WguiInternal("wgui/color_selector.xml"),
|
||||
extra: Default::default(),
|
||||
},
|
||||
layout,
|
||||
id_content,
|
||||
)?;
|
||||
|
||||
let slider_r = parser_state.fetch_component_as::<ComponentSlider>("slider_r")?;
|
||||
let slider_g = parser_state.fetch_component_as::<ComponentSlider>("slider_g")?;
|
||||
let slider_b = parser_state.fetch_component_as::<ComponentSlider>("slider_b")?;
|
||||
|
||||
{
|
||||
let mut lc = layout.start_common();
|
||||
let common = &mut lc.common();
|
||||
|
||||
slider_r.set_value(common, state.color.r * 255.0);
|
||||
slider_g.set_value(common, state.color.g * 255.0);
|
||||
slider_b.set_value(common, state.color.b * 255.0);
|
||||
}
|
||||
|
||||
slider_r.on_value_changed(self.gen_slider_callback(ColorIndex::Red));
|
||||
slider_g.on_value_changed(self.gen_slider_callback(ColorIndex::Green));
|
||||
slider_b.on_value_changed(self.gen_slider_callback(ColorIndex::Blue));
|
||||
|
||||
let id_rect_color = parser_state.get_widget_id("rect_color")?;
|
||||
|
||||
state.popup_state = Some(PopupState {
|
||||
slider_r,
|
||||
slider_g,
|
||||
slider_b,
|
||||
id_rect_color,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn gen_slider_callback(&self, idx: ColorIndex) -> SliderValueChangedCallback {
|
||||
let state = Rc::downgrade(&self.state);
|
||||
Box::new(move |common, evt| {
|
||||
let Some(state) = state.upgrade() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let mut state = state.borrow_mut();
|
||||
let Some(popup_state) = &state.popup_state else {
|
||||
return;
|
||||
};
|
||||
|
||||
let norm = evt.value / 255.0;
|
||||
|
||||
let mut new_color = state.color;
|
||||
match idx {
|
||||
ColorIndex::Red => new_color.r = norm,
|
||||
ColorIndex::Green => new_color.g = norm,
|
||||
ColorIndex::Blue => new_color.b = norm,
|
||||
}
|
||||
|
||||
if let Some(mut rect) = common
|
||||
.state
|
||||
.widgets
|
||||
.get_as::<WidgetRectangle>(popup_state.id_rect_color)
|
||||
{
|
||||
rect.set_color(common, new_color);
|
||||
}
|
||||
set_color_internal(&mut state, common, new_color);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_WIDTH: f32 = 96.0;
|
||||
const DEFAULT_HEIGHT: f32 = 32.0;
|
||||
|
||||
pub fn construct(
|
||||
ess: &mut ConstructEssentials,
|
||||
params: Params,
|
||||
) -> anyhow::Result<(WidgetPair, Rc<ComponentColorSelector>)> {
|
||||
let mut style = params.style;
|
||||
|
||||
if style.size.width.is_auto() {
|
||||
style.size.width = length(DEFAULT_WIDTH);
|
||||
}
|
||||
|
||||
if style.size.height.is_auto() {
|
||||
style.size.height = length(DEFAULT_HEIGHT);
|
||||
}
|
||||
|
||||
style.min_size = style.size;
|
||||
style.max_size = style.size;
|
||||
|
||||
let (widget_button, button) = button::construct(
|
||||
ess,
|
||||
button::Params {
|
||||
color: Some(params.color),
|
||||
round: WLength::Percent(1.0),
|
||||
border: 2.0,
|
||||
border_color: Some(drawing::Color::new(0.0, 0.0, 0.0, 1.0)),
|
||||
style,
|
||||
..Default::default()
|
||||
},
|
||||
)?;
|
||||
|
||||
let data = Rc::new(Data { button: button.clone() });
|
||||
|
||||
let state = Rc::new(RefCell::new(State {
|
||||
color: params.color,
|
||||
self_ref: Default::default(),
|
||||
wants_open: None,
|
||||
popup_state: None,
|
||||
on_changed: None,
|
||||
}));
|
||||
|
||||
let base = ComponentBase {
|
||||
id: widget_button.id,
|
||||
lhandles: Default::default(),
|
||||
};
|
||||
|
||||
let color_selector = Rc::new(ComponentColorSelector {
|
||||
base,
|
||||
data,
|
||||
state: state.clone(),
|
||||
window: WguiWindow::default(),
|
||||
});
|
||||
|
||||
let self_ref = Rc::downgrade(&color_selector);
|
||||
state.borrow_mut().self_ref = self_ref.clone();
|
||||
|
||||
button.on_click(Rc::new({
|
||||
let color_selector = color_selector.clone();
|
||||
move |common, evt| {
|
||||
let mut state = color_selector.state.borrow_mut();
|
||||
state.wants_open = Some(WantsOpen {
|
||||
position: evt.mouse_pos_absolute.unwrap_or_default(),
|
||||
});
|
||||
common.alterables.refresh_component_once(&self_ref);
|
||||
Ok(())
|
||||
}
|
||||
}));
|
||||
|
||||
ess.layout.defer_component_refresh(Component(color_selector.clone()));
|
||||
Ok((widget_button, color_selector))
|
||||
}
|
||||
|
|
@ -147,9 +147,15 @@ impl ComponentTrait for ComponentEditBox {
|
|||
}
|
||||
|
||||
fn refresh(&self, data: &mut RefreshData) {
|
||||
// FIXME: refactor this after merging feat-skybox-catalog branch
|
||||
let mut lc = data.layout.start_common();
|
||||
let mut common = lc.common();
|
||||
|
||||
let mut state = self.state.borrow_mut();
|
||||
let res = refresh_all(data.common, &self.data, &mut state);
|
||||
let res = refresh_all(&mut common, &self.data, &mut state);
|
||||
debug_assert!(res.is_some());
|
||||
|
||||
let _ = lc.finish();
|
||||
}
|
||||
|
||||
fn on_focus_change(&self, data: &mut FocusChangeData) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
use std::hash::Hash;
|
||||
use std::{hash::Hasher, rc::Rc};
|
||||
|
||||
use crate::layout::Layout;
|
||||
use crate::{
|
||||
any::AnyTrait,
|
||||
event::{CallbackDataCommon, EventListenerID},
|
||||
|
|
@ -10,6 +11,7 @@ use crate::{
|
|||
pub mod bar_graph;
|
||||
pub mod button;
|
||||
pub mod checkbox;
|
||||
pub mod color_selector;
|
||||
pub mod editbox;
|
||||
pub mod radio_group;
|
||||
pub mod slider;
|
||||
|
|
@ -17,7 +19,7 @@ pub mod tabs;
|
|||
pub mod tooltip;
|
||||
|
||||
pub struct RefreshData<'a> {
|
||||
pub common: &'a mut CallbackDataCommon<'a>,
|
||||
pub layout: &'a mut Layout,
|
||||
}
|
||||
|
||||
pub struct FocusChangeData<'a> {
|
||||
|
|
|
|||
|
|
@ -101,8 +101,7 @@ pub struct SliderValueChangedEvent {
|
|||
pub value: f32,
|
||||
}
|
||||
|
||||
pub type SliderValueChangedCallback =
|
||||
Box<dyn Fn(&mut CallbackDataCommon, SliderValueChangedEvent) -> anyhow::Result<()>>;
|
||||
pub type SliderValueChangedCallback = Box<dyn Fn(&mut CallbackDataCommon, SliderValueChangedEvent)>;
|
||||
|
||||
pub struct ComponentSlider {
|
||||
base: ComponentBase,
|
||||
|
|
@ -111,10 +110,14 @@ pub struct ComponentSlider {
|
|||
}
|
||||
|
||||
impl ComponentTrait for ComponentSlider {
|
||||
fn refresh(&self, init_data: &mut RefreshData) {
|
||||
fn refresh(&self, data: &mut RefreshData) {
|
||||
// FIXME: refactor this after merging feat-skybox-catalog branch
|
||||
let mut lc = data.layout.start_common();
|
||||
let mut common = lc.common();
|
||||
let mut state = self.state.borrow_mut();
|
||||
let value = state.values.value;
|
||||
state.set_value(init_data.common, &self.data, value);
|
||||
state.set_value(&mut common, &self.data, value);
|
||||
let _ = lc.finish();
|
||||
}
|
||||
|
||||
fn base(&self) -> &ComponentBase {
|
||||
|
|
@ -250,15 +253,13 @@ impl State {
|
|||
Self::update_text(common, &mut label, self.values.value);
|
||||
}
|
||||
|
||||
if changed
|
||||
&& let Some(on_value_changed) = &self.on_value_changed
|
||||
&& let Err(e) = on_value_changed(
|
||||
if changed && let Some(on_value_changed) = &self.on_value_changed {
|
||||
on_value_changed(
|
||||
common,
|
||||
SliderValueChangedEvent {
|
||||
value: self.values.value,
|
||||
},
|
||||
) {
|
||||
log::error!("{e:?}"); // FIXME: proper error handling
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ impl Boundary {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct Color {
|
||||
pub r: f32,
|
||||
pub g: f32,
|
||||
|
|
@ -179,6 +179,14 @@ impl Color {
|
|||
format!("#{r:02X}{g:02X}{b:02X}{a:02X}")
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn to_hex_rgb(&self) -> String {
|
||||
let r = (self.r.clamp(0.0, 1.0) * 255.0).round() as u8;
|
||||
let g = (self.g.clamp(0.0, 1.0) * 255.0).round() as u8;
|
||||
let b = (self.b.clamp(0.0, 1.0) * 255.0).round() as u8;
|
||||
format!("#{r:02X}{g:02X}{b:02X}")
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn as_arr(&self) -> [f32; 4] {
|
||||
[self.r, self.b, self.g, self.a]
|
||||
|
|
|
|||
|
|
@ -339,15 +339,14 @@ impl Layout {
|
|||
}
|
||||
|
||||
fn process_pending_components(&mut self, alterables: &mut EventAlterables) {
|
||||
for comp in &self.components_to_refresh_once {
|
||||
for comp in std::mem::take(&mut self.components_to_refresh_once) {
|
||||
let mut common = CallbackDataCommon {
|
||||
state: &self.state,
|
||||
alterables,
|
||||
};
|
||||
|
||||
comp.0.refresh(&mut RefreshData { common: &mut common });
|
||||
comp.0.refresh(&mut RefreshData { layout: self });
|
||||
}
|
||||
self.components_to_refresh_once.clear();
|
||||
}
|
||||
|
||||
fn process_pending_widget_ticks(&mut self, alterables: &mut EventAlterables) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
use crate::{
|
||||
components::{Component, color_selector},
|
||||
drawing,
|
||||
layout::WidgetID,
|
||||
parser::{AttribPair, ParserContext, process_component, style::parse_style},
|
||||
};
|
||||
|
||||
pub fn parse_component_color_selector(
|
||||
ctx: &mut ParserContext,
|
||||
parent_id: WidgetID,
|
||||
attribs: &[AttribPair],
|
||||
tag_name: &str,
|
||||
) -> anyhow::Result<WidgetID> {
|
||||
let style = parse_style(ctx, attribs, tag_name);
|
||||
let color = drawing::Color::new(1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
let (widget, component) = color_selector::construct(
|
||||
&mut ctx.get_construct_essentials(parent_id),
|
||||
color_selector::Params { color, style },
|
||||
)?;
|
||||
|
||||
process_component(ctx, Component(component), widget.id, attribs);
|
||||
|
||||
Ok(widget.id)
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
mod component_bar_graph;
|
||||
mod component_button;
|
||||
mod component_checkbox;
|
||||
mod component_color_selector;
|
||||
mod component_editbox;
|
||||
mod component_radio_group;
|
||||
mod component_slider;
|
||||
|
|
@ -25,6 +26,7 @@ use crate::{
|
|||
component_bar_graph::parse_component_bar_graph,
|
||||
component_button::parse_component_button,
|
||||
component_checkbox::{CheckboxKind, parse_component_checkbox},
|
||||
component_color_selector::parse_component_color_selector,
|
||||
component_editbox::parse_component_editbox,
|
||||
component_radio_group::parse_component_radio_group,
|
||||
component_slider::parse_component_slider,
|
||||
|
|
@ -1063,6 +1065,7 @@ fn parse_child<'a>(
|
|||
"Slider" => {
|
||||
new_widget_id = Some(parse_component_slider(ctx, parent_id, &attribs, tag_name)?);
|
||||
}
|
||||
"ColorSelector" => new_widget_id = Some(parse_component_color_selector(ctx, parent_id, &attribs, tag_name)?),
|
||||
"CheckBox" => {
|
||||
new_widget_id = Some(parse_component_checkbox(
|
||||
ctx,
|
||||
|
|
|
|||
|
|
@ -94,7 +94,6 @@ impl ContextMenu {
|
|||
let globals = layout.state.globals.clone();
|
||||
|
||||
self.window.open(&mut WguiWindowParams {
|
||||
globals: &globals,
|
||||
layout,
|
||||
position: params.position,
|
||||
extra: WguiWindowParamsExtra {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,6 @@ impl Default for WguiWindowParamsExtra {
|
|||
|
||||
pub struct WguiWindowParams<'a> {
|
||||
pub position: Vec2,
|
||||
pub globals: &'a WguiGlobals,
|
||||
pub layout: &'a mut Layout,
|
||||
pub extra: WguiWindowParamsExtra,
|
||||
}
|
||||
|
|
@ -100,7 +99,7 @@ impl WguiWindow {
|
|||
self.0.borrow_mut().opened_window = None;
|
||||
}
|
||||
|
||||
pub fn open(&mut self, params: &mut WguiWindowParams) -> anyhow::Result<()> {
|
||||
pub fn open(&self, params: &mut WguiWindowParams) -> anyhow::Result<()> {
|
||||
// close previous one if it's already open
|
||||
self.close();
|
||||
|
||||
|
|
@ -216,12 +215,14 @@ impl WguiWindow {
|
|||
},
|
||||
)?;
|
||||
|
||||
let globals = params.layout.state.globals.clone();
|
||||
|
||||
let content_id = if params.extra.with_decorations {
|
||||
let xml_path: AssetPath = AssetPath::WguiInternal("wgui/window_frame.xml");
|
||||
|
||||
let state = parser::parse_from_assets(
|
||||
&parser::ParseDocumentParams {
|
||||
globals: params.globals.clone(),
|
||||
globals: globals.clone(),
|
||||
path: xml_path,
|
||||
extra: Default::default(),
|
||||
},
|
||||
|
|
@ -240,7 +241,7 @@ impl WguiWindow {
|
|||
|
||||
if let Some(title) = ¶ms.extra.title {
|
||||
let mut text_title = state.fetch_widget_as::<WidgetLabel>(¶ms.layout.state, "text_window_title")?;
|
||||
text_title.set_text_simple(&mut params.globals.get(), title.clone());
|
||||
text_title.set_text_simple(&mut globals.get(), title.clone());
|
||||
}
|
||||
let content = state.fetch_widget(¶ms.layout.state, "content")?;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue