wgui: add set_color for Button, dash-frontend: audio_settings: button highlights
This commit is contained in:
@@ -145,10 +145,6 @@ pub fn set_default_sink(sink_index: u32) -> anyhow::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sink_from_index(sinks: &[Sink], index: u32) -> Option<&Sink> {
|
|
||||||
sinks.iter().find(|&sink| sink.index == index)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_sink_volume(sink: &Sink) -> anyhow::Result<f32> {
|
pub fn get_sink_volume(sink: &Sink) -> anyhow::Result<f32> {
|
||||||
let volume_channel = {
|
let volume_channel = {
|
||||||
if let Some(front_left) = &sink.volume.front_left {
|
if let Some(front_left) = &sink.volume.front_left {
|
||||||
@@ -240,10 +236,6 @@ pub fn set_default_source(source_index: u32) -> anyhow::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_source_from_index(sources: &[Source], index: u32) -> Option<&Source> {
|
|
||||||
sources.iter().find(|&source| source.index == index)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_source_volume(source: &Source) -> anyhow::Result<f32> {
|
pub fn get_source_volume(source: &Source) -> anyhow::Result<f32> {
|
||||||
let volume_channel = {
|
let volume_channel = {
|
||||||
if let Some(front_left) = &source.volume.front_left {
|
if let Some(front_left) = &source.volume.front_left {
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ enum CurrentMode {
|
|||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
enum SearchType {
|
enum SearchType {
|
||||||
Sink,
|
Sink,
|
||||||
Source,
|
#[allow(dead_code)]
|
||||||
|
Source, // might be useful in the future
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@@ -75,6 +76,10 @@ pub struct View {
|
|||||||
mode: CurrentMode,
|
mode: CurrentMode,
|
||||||
|
|
||||||
id_devices: WidgetID,
|
id_devices: WidgetID,
|
||||||
|
|
||||||
|
btn_sinks: Rc<ComponentButton>,
|
||||||
|
btn_sources: Rc<ComponentButton>,
|
||||||
|
btn_cards: Rc<ComponentButton>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Params<'a> {
|
pub struct Params<'a> {
|
||||||
@@ -596,6 +601,9 @@ impl View {
|
|||||||
id_devices,
|
id_devices,
|
||||||
tasks,
|
tasks,
|
||||||
on_update: params.on_update,
|
on_update: params.on_update,
|
||||||
|
btn_sinks: btn_sinks.clone(),
|
||||||
|
btn_sources: btn_sources.clone(),
|
||||||
|
btn_cards: btn_cards.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
btn_sinks.on_click(res.handle_func_button_click(ViewTask::SetMode(CurrentMode::Sinks)));
|
btn_sinks.on_click(res.handle_func_button_click(ViewTask::SetMode(CurrentMode::Sinks)));
|
||||||
@@ -604,10 +612,43 @@ impl View {
|
|||||||
btn_auto.on_click(res.handle_func_button_click(ViewTask::AutoSwitch));
|
btn_auto.on_click(res.handle_func_button_click(ViewTask::AutoSwitch));
|
||||||
|
|
||||||
res.init_mode_sinks(params.layout)?;
|
res.init_mode_sinks(params.layout)?;
|
||||||
|
res.update_button_highlights(params.layout)?;
|
||||||
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn update_button_highlights(&self, layout: &mut Layout) -> anyhow::Result<()> {
|
||||||
|
let defaults = self.globals.defaults();
|
||||||
|
|
||||||
|
let mut c = layout.start_common();
|
||||||
|
let mut common = c.common();
|
||||||
|
|
||||||
|
let num: u8 = match &self.mode {
|
||||||
|
CurrentMode::Sinks => 0,
|
||||||
|
CurrentMode::Sources => 1,
|
||||||
|
CurrentMode::Cards => 2,
|
||||||
|
CurrentMode::CardProfileSelector(_) => 255,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut perform = |btn_num: u8, btn: &Rc<ComponentButton>| {
|
||||||
|
btn.set_color(
|
||||||
|
&mut common,
|
||||||
|
if num == btn_num {
|
||||||
|
defaults.accent_color
|
||||||
|
} else {
|
||||||
|
defaults.button_color
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
perform(0, &self.btn_sinks);
|
||||||
|
perform(1, &self.btn_sources);
|
||||||
|
perform(2, &self.btn_cards);
|
||||||
|
|
||||||
|
c.finish()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn process_tasks(&mut self, layout: &mut Layout) -> anyhow::Result<bool> {
|
fn process_tasks(&mut self, layout: &mut Layout) -> anyhow::Result<bool> {
|
||||||
let tasks = self.tasks.drain();
|
let tasks = self.tasks.drain();
|
||||||
if tasks.is_empty() {
|
if tasks.is_empty() {
|
||||||
@@ -619,12 +660,15 @@ impl View {
|
|||||||
|
|
||||||
for task in tasks {
|
for task in tasks {
|
||||||
match task {
|
match task {
|
||||||
ViewTask::Remount => match &self.mode {
|
ViewTask::Remount => {
|
||||||
CurrentMode::Sinks => self.init_mode_sinks(layout)?,
|
self.update_button_highlights(layout)?;
|
||||||
CurrentMode::Sources => self.init_mode_sources(layout)?,
|
match &self.mode {
|
||||||
CurrentMode::Cards => self.init_mode_cards(layout)?,
|
CurrentMode::Sinks => self.init_mode_sinks(layout)?,
|
||||||
CurrentMode::CardProfileSelector(card) => self.init_mode_card_selector(layout, card.clone())?,
|
CurrentMode::Sources => self.init_mode_sources(layout)?,
|
||||||
},
|
CurrentMode::Cards => self.init_mode_cards(layout)?,
|
||||||
|
CurrentMode::CardProfileSelector(card) => self.init_mode_card_selector(layout, card.clone())?,
|
||||||
|
}
|
||||||
|
}
|
||||||
ViewTask::SetSinkVolume(s) => {
|
ViewTask::SetSinkVolume(s) => {
|
||||||
set_sink_volume = Some(s);
|
set_sink_volume = Some(s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,19 +65,23 @@ impl Default for Params<'_> {
|
|||||||
pub struct ButtonClickEvent {}
|
pub struct ButtonClickEvent {}
|
||||||
pub type ButtonClickCallback = Box<dyn Fn(&mut CallbackDataCommon, ButtonClickEvent) -> anyhow::Result<()>>;
|
pub type ButtonClickCallback = Box<dyn Fn(&mut CallbackDataCommon, ButtonClickEvent) -> anyhow::Result<()>>;
|
||||||
|
|
||||||
|
pub struct Colors {
|
||||||
|
pub color: drawing::Color,
|
||||||
|
pub border_color: drawing::Color,
|
||||||
|
pub hover_color: drawing::Color,
|
||||||
|
pub hover_border_color: drawing::Color,
|
||||||
|
}
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
hovered: bool,
|
hovered: bool,
|
||||||
down: bool,
|
down: bool,
|
||||||
sticky_down: bool,
|
sticky_down: bool,
|
||||||
on_click: Option<ButtonClickCallback>,
|
on_click: Option<ButtonClickCallback>,
|
||||||
active_tooltip: Option<Rc<ComponentTooltip>>,
|
active_tooltip: Option<Rc<ComponentTooltip>>,
|
||||||
|
colors: Colors,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Data {
|
struct Data {
|
||||||
initial_color: drawing::Color,
|
|
||||||
initial_border_color: drawing::Color,
|
|
||||||
initial_hover_color: drawing::Color,
|
|
||||||
initial_hover_border_color: drawing::Color,
|
|
||||||
id_label: WidgetID, // Label
|
id_label: WidgetID, // Label
|
||||||
id_rect: WidgetID, // Rectangle
|
id_rect: WidgetID, // Rectangle
|
||||||
sticky: bool,
|
sticky: bool,
|
||||||
@@ -114,6 +118,10 @@ impl ComponentTrait for ComponentButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_color2(color: &drawing::Color) -> drawing::Color {
|
||||||
|
color.lerp(&Color::new(0.0, 0.0, 0.0, color.a), 0.2)
|
||||||
|
}
|
||||||
|
|
||||||
impl ComponentButton {
|
impl ComponentButton {
|
||||||
pub fn get_label(&self) -> WidgetID {
|
pub fn get_label(&self) -> WidgetID {
|
||||||
self.data.id_label
|
self.data.id_label
|
||||||
@@ -131,6 +139,18 @@ impl ComponentButton {
|
|||||||
label.set_text(common, text);
|
label.set_text(common, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_color(&self, common: &mut CallbackDataCommon, color: Color) {
|
||||||
|
let Some(mut rect) = common.state.widgets.get_as::<WidgetRectangle>(self.data.id_rect) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut state = self.state.borrow_mut();
|
||||||
|
state.colors.color = color;
|
||||||
|
|
||||||
|
rect.params.color = color;
|
||||||
|
rect.params.color2 = get_color2(&color);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn on_click(&self, func: ButtonClickCallback) {
|
pub fn on_click(&self, func: ButtonClickCallback) {
|
||||||
self.state.borrow_mut().on_click = Some(func);
|
self.state.borrow_mut().on_click = Some(func);
|
||||||
}
|
}
|
||||||
@@ -150,7 +170,7 @@ impl ComponentButton {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let data = self.data.clone();
|
let state = self.state.clone();
|
||||||
let anim = Animation::new(
|
let anim = Animation::new(
|
||||||
self.data.id_rect,
|
self.data.id_rect,
|
||||||
if sticky_down { 5 } else { 10 },
|
if sticky_down { 5 } else { 10 },
|
||||||
@@ -163,10 +183,12 @@ impl ComponentButton {
|
|||||||
1.0 - anim_data.pos
|
1.0 - anim_data.pos
|
||||||
};
|
};
|
||||||
|
|
||||||
let bgcolor = data.initial_color.lerp(&data.initial_hover_color, mult * 0.5);
|
let state = state.borrow();
|
||||||
|
let colors = &state.colors;
|
||||||
|
let bgcolor = colors.color.lerp(&colors.hover_color, mult * 0.5);
|
||||||
rect.params.color = bgcolor;
|
rect.params.color = bgcolor;
|
||||||
rect.params.color2 = get_color2(&bgcolor);
|
rect.params.color2 = get_color2(&bgcolor);
|
||||||
rect.params.border_color = data.initial_border_color.lerp(&data.initial_hover_border_color, mult);
|
rect.params.border_color = colors.border_color.lerp(&colors.hover_border_color, mult);
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -175,14 +197,10 @@ impl ComponentButton {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_color2(color: &drawing::Color) -> drawing::Color {
|
|
||||||
color.lerp(&Color::new(0.0, 0.0, 0.0, color.a), 0.2)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn anim_hover(
|
fn anim_hover(
|
||||||
rect: &mut WidgetRectangle,
|
rect: &mut WidgetRectangle,
|
||||||
widget_data: &mut WidgetData,
|
widget_data: &mut WidgetData,
|
||||||
data: &Data,
|
colors: &Colors,
|
||||||
widget_boundary: Boundary,
|
widget_boundary: Boundary,
|
||||||
pos: f32,
|
pos: f32,
|
||||||
pressed: bool,
|
pressed: bool,
|
||||||
@@ -191,15 +209,12 @@ fn anim_hover(
|
|||||||
let mult = pos * if pressed { 1.5 } else { 1.0 };
|
let mult = pos * if pressed { 1.5 } else { 1.0 };
|
||||||
|
|
||||||
let (init_border_color, init_color) = if sticky_down {
|
let (init_border_color, init_color) = if sticky_down {
|
||||||
(
|
(colors.hover_border_color, colors.color.lerp(&colors.hover_color, 0.5))
|
||||||
data.initial_hover_border_color,
|
|
||||||
data.initial_color.lerp(&data.initial_hover_color, 0.5),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
(data.initial_border_color, data.initial_color)
|
(colors.border_color, colors.color)
|
||||||
};
|
};
|
||||||
|
|
||||||
let bgcolor = init_color.lerp(&data.initial_hover_color, mult);
|
let bgcolor = init_color.lerp(&colors.hover_color, mult);
|
||||||
|
|
||||||
//let t = Mat4::from_scale(Vec3::splat(1.0 + pos * 0.5)) * Mat4::from_rotation_z(pos * 1.0);
|
//let t = Mat4::from_scale(Vec3::splat(1.0 + pos * 0.5)) * Mat4::from_rotation_z(pos * 1.0);
|
||||||
|
|
||||||
@@ -209,10 +224,10 @@ fn anim_hover(
|
|||||||
rect.params.color = bgcolor;
|
rect.params.color = bgcolor;
|
||||||
rect.params.color2 = get_color2(&bgcolor);
|
rect.params.color2 = get_color2(&bgcolor);
|
||||||
|
|
||||||
rect.params.border_color = init_border_color.lerp(&data.initial_hover_border_color, mult);
|
rect.params.border_color = init_border_color.lerp(&colors.hover_border_color, mult);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn anim_hover_create(data: Rc<Data>, state: Rc<RefCell<State>>, widget_id: WidgetID, fade_in: bool) -> Animation {
|
fn anim_hover_create(state: Rc<RefCell<State>>, widget_id: WidgetID, fade_in: bool) -> Animation {
|
||||||
Animation::new(
|
Animation::new(
|
||||||
widget_id,
|
widget_id,
|
||||||
if fade_in { 5 } else { 10 },
|
if fade_in { 5 } else { 10 },
|
||||||
@@ -223,7 +238,7 @@ fn anim_hover_create(data: Rc<Data>, state: Rc<RefCell<State>>, widget_id: Widge
|
|||||||
anim_hover(
|
anim_hover(
|
||||||
rect,
|
rect,
|
||||||
anim_data.data,
|
anim_data.data,
|
||||||
&data,
|
&state.colors,
|
||||||
anim_data.widget_boundary,
|
anim_data.widget_boundary,
|
||||||
if fade_in { anim_data.pos } else { 1.0 - anim_data.pos },
|
if fade_in { anim_data.pos } else { 1.0 - anim_data.pos },
|
||||||
state.down,
|
state.down,
|
||||||
@@ -245,12 +260,9 @@ fn register_event_mouse_enter(
|
|||||||
Box::new(move |common, event_data, (), ()| {
|
Box::new(move |common, event_data, (), ()| {
|
||||||
common.alterables.trigger_haptics();
|
common.alterables.trigger_haptics();
|
||||||
common.alterables.mark_redraw();
|
common.alterables.mark_redraw();
|
||||||
common.alterables.animate(anim_hover_create(
|
common
|
||||||
data.clone(),
|
.alterables
|
||||||
state.clone(),
|
.animate(anim_hover_create(state.clone(), event_data.widget_id, true));
|
||||||
event_data.widget_id,
|
|
||||||
true,
|
|
||||||
));
|
|
||||||
|
|
||||||
if let Some(info) = info.clone() {
|
if let Some(info) = info.clone() {
|
||||||
common.alterables.tasks.push(LayoutTask::ModifyLayoutState({
|
common.alterables.tasks.push(LayoutTask::ModifyLayoutState({
|
||||||
@@ -270,21 +282,14 @@ fn register_event_mouse_enter(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_event_mouse_leave(
|
fn register_event_mouse_leave(state: Rc<RefCell<State>>, listeners: &mut EventListenerCollection) -> EventListenerID {
|
||||||
data: Rc<Data>,
|
|
||||||
state: Rc<RefCell<State>>,
|
|
||||||
listeners: &mut EventListenerCollection,
|
|
||||||
) -> EventListenerID {
|
|
||||||
listeners.register(
|
listeners.register(
|
||||||
EventListenerKind::MouseLeave,
|
EventListenerKind::MouseLeave,
|
||||||
Box::new(move |common, event_data, (), ()| {
|
Box::new(move |common, event_data, (), ()| {
|
||||||
common.alterables.trigger_haptics();
|
common.alterables.trigger_haptics();
|
||||||
common.alterables.animate(anim_hover_create(
|
common
|
||||||
data.clone(),
|
.alterables
|
||||||
state.clone(),
|
.animate(anim_hover_create(state.clone(), event_data.widget_id, false));
|
||||||
event_data.widget_id,
|
|
||||||
false,
|
|
||||||
));
|
|
||||||
let mut state = state.borrow_mut();
|
let mut state = state.borrow_mut();
|
||||||
state.active_tooltip = None;
|
state.active_tooltip = None;
|
||||||
state.hovered = false;
|
state.hovered = false;
|
||||||
@@ -293,11 +298,7 @@ fn register_event_mouse_leave(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_event_mouse_press(
|
fn register_event_mouse_press(state: Rc<RefCell<State>>, listeners: &mut EventListenerCollection) -> EventListenerID {
|
||||||
data: Rc<Data>,
|
|
||||||
state: Rc<RefCell<State>>,
|
|
||||||
listeners: &mut EventListenerCollection,
|
|
||||||
) -> EventListenerID {
|
|
||||||
listeners.register(
|
listeners.register(
|
||||||
EventListenerKind::MousePress,
|
EventListenerKind::MousePress,
|
||||||
Box::new(move |common, event_data, (), ()| {
|
Box::new(move |common, event_data, (), ()| {
|
||||||
@@ -307,7 +308,7 @@ fn register_event_mouse_press(
|
|||||||
anim_hover(
|
anim_hover(
|
||||||
rect,
|
rect,
|
||||||
event_data.widget_data,
|
event_data.widget_data,
|
||||||
&data,
|
&state.colors,
|
||||||
common.state.get_node_boundary(event_data.node_id),
|
common.state.get_node_boundary(event_data.node_id),
|
||||||
1.0,
|
1.0,
|
||||||
true,
|
true,
|
||||||
@@ -345,7 +346,7 @@ fn register_event_mouse_release(
|
|||||||
anim_hover(
|
anim_hover(
|
||||||
rect,
|
rect,
|
||||||
event_data.widget_data,
|
event_data.widget_data,
|
||||||
&data,
|
&state.colors,
|
||||||
common.state.get_node_boundary(event_data.node_id),
|
common.state.get_node_boundary(event_data.node_id),
|
||||||
1.0,
|
1.0,
|
||||||
false,
|
false,
|
||||||
@@ -488,10 +489,6 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
|||||||
let data = Rc::new(Data {
|
let data = Rc::new(Data {
|
||||||
id_label,
|
id_label,
|
||||||
id_rect,
|
id_rect,
|
||||||
initial_color: color,
|
|
||||||
initial_border_color: border_color,
|
|
||||||
initial_hover_color: hover_color,
|
|
||||||
initial_hover_border_color: hover_border_color,
|
|
||||||
sticky: params.sticky,
|
sticky: params.sticky,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -501,6 +498,12 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
|||||||
on_click: None,
|
on_click: None,
|
||||||
active_tooltip: None,
|
active_tooltip: None,
|
||||||
sticky_down: false,
|
sticky_down: false,
|
||||||
|
colors: Colors {
|
||||||
|
color,
|
||||||
|
border_color,
|
||||||
|
hover_color,
|
||||||
|
hover_border_color,
|
||||||
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let base = ComponentBase {
|
let base = ComponentBase {
|
||||||
@@ -509,8 +512,8 @@ pub fn construct(ess: &mut ConstructEssentials, params: Params) -> anyhow::Resul
|
|||||||
let mut widget = ess.layout.state.widgets.get(id_rect).unwrap().state();
|
let mut widget = ess.layout.state.widgets.get(id_rect).unwrap().state();
|
||||||
vec![
|
vec![
|
||||||
register_event_mouse_enter(data.clone(), state.clone(), &mut widget.event_listeners, params.tooltip),
|
register_event_mouse_enter(data.clone(), state.clone(), &mut widget.event_listeners, params.tooltip),
|
||||||
register_event_mouse_leave(data.clone(), state.clone(), &mut widget.event_listeners),
|
register_event_mouse_leave(state.clone(), &mut widget.event_listeners),
|
||||||
register_event_mouse_press(data.clone(), state.clone(), &mut widget.event_listeners),
|
register_event_mouse_press(state.clone(), &mut widget.event_listeners),
|
||||||
register_event_mouse_release(data.clone(), state.clone(), &mut widget.event_listeners),
|
register_event_mouse_release(data.clone(), state.clone(), &mut widget.event_listeners),
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cell::{RefCell, RefMut},
|
cell::{Ref, RefCell, RefMut},
|
||||||
io::Read,
|
io::Read,
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
@@ -93,6 +93,10 @@ impl WguiGlobals {
|
|||||||
RefMut::map(self.0.borrow_mut(), |x| &mut x.i18n_builtin)
|
RefMut::map(self.0.borrow_mut(), |x| &mut x.i18n_builtin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn defaults(&self) -> Ref<'_, Defaults> {
|
||||||
|
Ref::map(self.0.borrow(), |x| &x.defaults)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn assets_internal(&self) -> RefMut<'_, Box<dyn AssetProvider>> {
|
pub fn assets_internal(&self) -> RefMut<'_, Box<dyn AssetProvider>> {
|
||||||
RefMut::map(self.0.borrow_mut(), |x| &mut x.assets_internal)
|
RefMut::map(self.0.borrow_mut(), |x| &mut x.assets_internal)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user