window.rs 6.13 KB
Newer Older
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
1
use super::application::Action;
2
3
4
5
6
7
use super::colour_entry::ColourEntry;
use super::config::{APP_ID, PROFILE};
use super::contrast_level::ContrastLevelBar;
use super::contrast_preview::ContrastPreview;
use super::window_state::WindowState;

8
use gettextrs::gettext;
9
use gio::prelude::*;
10
use glib::ObjectExt;
11
use gtk::prelude::*;
12
use libhandy::HeaderBarExt;
13
use std::{cell::RefCell, rc::Rc};
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
14
15
16
17

pub struct Window {
    pub widget: gtk::ApplicationWindow,
    appmenu_button: gtk::MenuButton,
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
18
19
    fg_entry: ColourEntry,
    bg_entry: ColourEntry,
20
    reverse_btn: gtk::Button,
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
21
    headerbar: libhandy::HeaderBar,
22
    pub state: Rc<RefCell<WindowState>>,
23
24
    pub levelbar: Rc<RefCell<ContrastLevelBar>>,
    pub preview: Rc<RefCell<ContrastPreview>>,
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
25
    sender: glib::Sender<Action>,
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
26
27
28
}

impl Window {
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
29
    pub fn new(sender: glib::Sender<Action>) -> Self {
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
30
        let settings = gio::Settings::new(APP_ID);
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
31
        let builder = gtk::Builder::new_from_resource("/org/gnome/design/Contrast/window.ui");
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
32
        let widget: gtk::ApplicationWindow = builder.get_object("window").unwrap();
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
33
        let headerbar: libhandy::HeaderBar = builder.get_object("headerbar").unwrap();
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
34
35
        let appmenu_button: gtk::MenuButton = builder.get_object("appmenu_button").unwrap();

36
37
        let bg_entry = ColourEntry::new(gettext("Background Colour"));
        let fg_entry = ColourEntry::new(gettext("Foreground Colour"));
38

39
40
        let reverse_btn = gtk::Button::new();

41
        let state = Rc::new(RefCell::new(WindowState::init(settings)));
42

43
44
        let levelbar = Rc::new(RefCell::new(ContrastLevelBar::new()));
        let preview = Rc::new(RefCell::new(ContrastPreview::new()));
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
45

Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
46
47
48
49
        if PROFILE == "Devel" {
            widget.get_style_context().add_class("devel");
        }

Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
50
51
52
53
54
        let window = Window {
            widget,
            appmenu_button,
            fg_entry,
            bg_entry,
55
            reverse_btn,
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
56
            headerbar,
57
58
59
            state,
            levelbar,
            preview,
Zander Brown's avatar
Zander Brown committed
60
            sender,
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
61
        };
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
62

Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
63
        window.init();
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
64
        window.setup_widgets();
65
        window.setup_signals();
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
66
67
68
        window
    }

Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
69
    fn init(&self) {
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
70
        self.widget.get_style_context().add_class("main-window");
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
71
        // setup app menu
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
72
        let menu_builder = gtk::Builder::new_from_resource("/org/gnome/design/Contrast/menu.ui");
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
73
74
75
        let popover_menu: gio::MenuModel = menu_builder.get_object("popover_menu").unwrap();
        self.appmenu_button.set_menu_model(Some(&popover_menu));
        // save window state on delete event
76
77

        let state = self.state.clone();
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
78
        self.widget.connect_delete_event(move |window, _| {
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
79
80
81
            if let Err(err) = state.borrow_mut().dump(&window) {
                warn!("Failed to save window state {}", err);
            }
82
            gtk::Inhibit(false)
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
83
84
        });

Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
85
        self.widget.show();
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
86
    }
87
88
    fn setup_signals(&self) {
        let state = self.state.clone();
89
90
91
92
93
94
95
96
97
98
        let fg_entry = self.fg_entry.clone();
        let bg_entry = self.bg_entry.clone();
        let sender = self.sender.clone();
        let on_entry_changed = move |_entry: &gtk::Entry| {
            let fg_colour = fg_entry.get_text();
            let bg_colour = bg_entry.get_text();

            state.borrow_mut().set_bg_colour(Some(&bg_colour));
            state.borrow_mut().set_fg_colour(Some(&fg_colour));

Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
99
            sender.send(Action::ColorChanged).ok(); // never fails
100
        };
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
101

102
103
        let bg_handle = self.bg_entry.entry.connect_changed(on_entry_changed.clone());
        let fg_handle = self.fg_entry.entry.connect_changed(on_entry_changed.clone());
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
104

105
        let state = self.state.clone();
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
106
107
        let fg_entry = self.fg_entry.clone();
        let bg_entry = self.bg_entry.clone();
Zander Brown's avatar
Zander Brown committed
108
        let sender = self.sender.clone();
109
110
111
112

        let actions = gio::SimpleActionGroup::new();
        let reverse_colors = gio::SimpleAction::new("reverse-colors", None);
        reverse_colors.connect_activate(move |_, _| {
113
114
            fg_entry.entry.block_signal(&fg_handle);
            bg_entry.entry.block_signal(&bg_handle);
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
115
116
            let fg_colour = fg_entry.get_text();
            let bg_colour = bg_entry.get_text();
117
118
119
120
121
            fg_entry.set_text(Some(bg_colour.clone()));
            bg_entry.set_text(Some(fg_colour.clone()));
            fg_entry.entry.unblock_signal(&fg_handle);
            bg_entry.entry.unblock_signal(&bg_handle);

122
123
            state.borrow_mut().set_bg_colour(Some(&fg_colour));
            state.borrow_mut().set_fg_colour(Some(&bg_colour));
Zander Brown's avatar
Zander Brown committed
124

Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
125
            sender.send(Action::ColorChanged).ok(); // never fails
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
126
        });
127
128
129
        actions.add_action(&reverse_colors);

        self.widget.insert_action_group("window", Some(&actions));
130
131
132
133
134
    }

    fn setup_widgets(&self) {
        let container = gtk::Box::new(gtk::Orientation::Vertical, 0);
        container.get_style_context().add_class("main-container");
135
        container.set_valign(gtk::Align::Center);
136
137
        container.show();

138
139
140
        self.fg_entry.entry.get_style_context().add_class("fg-entry");
        self.bg_entry.entry.get_style_context().add_class("bg-entry");

141
        self.reverse_btn.set_halign(gtk::Align::Center);
142
        self.reverse_btn.set_action_name(Some("window.reverse-colors"));
143
144
145
146
        let reverse_img = gtk::Image::new_from_icon_name(Some("network-transmit-receive-symbolic"), gtk::IconSize::Button);
        reverse_img.show();
        self.reverse_btn.set_image(Some(&reverse_img));
        self.reverse_btn.show();
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
147

Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
148
        let entries_container = gtk::Box::new(gtk::Orientation::Horizontal, 0);
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
149
        entries_container.pack_start(&self.bg_entry.widget, false, false, 6);
150
        entries_container.pack_start(&self.reverse_btn, false, false, 6);
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
151
152
153
        entries_container.pack_start(&self.fg_entry.widget, false, false, 6);
        entries_container.set_halign(gtk::Align::Center);
        entries_container.show();
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
154
        self.headerbar.set_custom_title(Some(&entries_container));
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
155

156
157
        container.pack_start(&self.preview.borrow().widget, true, true, 12);
        container.pack_start(&self.levelbar.borrow().widget, true, true, 12);
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
158
159

        self.widget.add(&container);
160
161
        // Restore state
        self.state.borrow_mut().load_into(&self.widget, &self.bg_entry, &self.fg_entry);
Bilal Elmoussaoui's avatar
Bilal Elmoussaoui committed
162
    }
Bilal Elmoussaoui's avatar
Init  
Bilal Elmoussaoui committed
163
}