~jatone/wds

wds/src/console/systemtray/meta/mod.rs -rw-r--r-- 4.8 KiB
4e27669dJames Lawrence distribution release 9 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
use druid;
use druid::WidgetExt;

use crate::console;
use crate::console::widget::ext::position::clicks::ClicksExt;
use crate::console::widget::ext::stateful::StatefulExt;
use crate::console::widget::ext::position::hover::InteractiveExt;

use super::audio;
use super::battery;
use super::network::networkmanager::network;

mod power;

pub fn new() -> Meta {
    Meta::default()
}

#[derive(Clone, Default, std::fmt::Debug, druid::Data, druid::Lens)]
pub struct State {
    text: String,
    audio: audio::Audio,
    battery: battery::State,
    network: network::State,
}

#[derive(Clone)]
pub struct Meta {
    state: std::sync::Arc<std::cell::RefCell<State>>,
}

impl Default for Meta {
    fn default() -> Self {
        Self {
            state: std::sync::Arc::new(std::cell::RefCell::new(State::default())),
        }
    }
}

impl<T: druid::Data + std::fmt::Debug> console::systemtray::TrayWidget<T, druid::widget::Container<T>> for Meta {
    fn widget(&self) -> druid::widget::Container<T> {
        druid::widget::Container::new(
            druid::widget::Container::<State>::new(
                    druid::widget::Flex::row()
                        .with_default_spacer()
                        .with_child(
                            druid::widget::Container::new(battery::icon())
                            .fix_height(12.)
                            .controller(battery::Controller)
                            .lens(State::battery)
                        )
                        .with_child(
                            audio::icon()
                            .controller(audio::Controller::default())
                            .lens(State::audio)
                        )
                        .with_default_spacer()
                        .with_child(
                            network::icon((0., 0.))
                            .controller(network::Controller)
                            .lens(State::network)
                        )
                        .with_default_spacer()
                        .with_child(
                            druid::widget::SizedBox::new(druid::widget::Svg::new(console::icons::power()))
                            .width(18.0)
                            .height(18.0),
                        )
                        .with_default_spacer()
                        .on_single_click({
                            move |env: &druid::Env, ctx, click, _widget, data: &mut State| {
                                let _winid = console::widget::context::menu(
                                    env,
                                    ctx,
                                    data,
                                    click,
                                    console::systemtray::contextmenu(Context).on_event({
                                        let wid = ctx.widget_id();
                                        move |_env, ctx, _w, event, _data| {
                                            match event {
                                                druid::Event::Command(cmd) => ctx.submit_command(cmd.clone().to(druid::Target::Widget(wid))),
                                                _ => { /* ignored */ },
                                            }
                                        }
                                    }),
                                    druid::Size::new(150., 1.),
                                );
                            }
                        })
                        .expand_height()
            )
            .interactive()
            .lens(self.clone())
        )
    }
}

struct Context;
impl console::systemtray::ContextWidget<State, druid::widget::Container<State>> for Context {
    fn widget(&self) -> druid::widget::Container<State> {
        druid::widget::Container::new(
            druid::widget::Container::new(
                druid::widget::Flex::column()
                .with_default_spacer()
                .with_child(
                    druid::widget::Flex::row()
                        .with_default_spacer()
                        .with_child(console::theme::icons::volume(&100.))
                        .with_default_spacer()
                        .with_child(audio::slider())
                        .with_default_spacer()
                        .lens(State::audio).expand_width()
                )
                .with_default_spacer()
                .with_child(power::menu())
                .with_default_spacer()
            ).fix_width(156.)
        )
    }
}

impl<T: ?Sized + std::fmt::Debug> druid::Lens<T, State> for Meta {
    fn with<V, F: FnOnce(&State) -> V>(&self, _data: &T, f: F) -> V {
        f(&self.state.borrow())
    }

    fn with_mut<V, F: FnOnce(&mut State) -> V>(&self, _data: &mut T, f: F) -> V {
        let mut updated = self.state.borrow().clone();
        let v = f(&mut updated);
        self.state.replace(updated.clone());
        v
    }
}