Commit 8bb01b80 authored by Bilal Elmoussaoui's avatar Bilal Elmoussaoui
Browse files

use gtk-macros

parent d5371c09
Pipeline #161541 passed with stage
in 9 minutes and 12 seconds
......@@ -119,6 +119,7 @@ dependencies = [
"gio 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"glib 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"gtk 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"gtk-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libhandy 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"pango 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -405,6 +406,11 @@ dependencies = [
"pango-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "gtk-macros"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "gtk-sys"
version = "0.9.2"
......@@ -834,6 +840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum glib-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "95856f3802f446c05feffa5e24859fe6a183a7cb849c8449afc35c86b1e316e2"
"checksum gobject-sys 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31d1a804f62034eccf370006ccaef3708a71c31d561fee88564abe71177553d9"
"checksum gtk 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "87e1e8d70290239c668594002d1b174fcc7d7ef5d26670ee141490ede8facf8f"
"checksum gtk-macros 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1874c48e670519ce192093ac906c08a6dde7cb2d18b28722ef237726a39c3a63"
"checksum gtk-sys 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53def660c7b48b00b510c81ef2d2fbd3c570f1527081d8d7947f471513e1a4c1"
"checksum hermit-abi 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "e2c55f143919fbc0bc77e427fe2d74cf23786d7c1875666f2fde3ac3c659bb67"
"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
......
......@@ -19,3 +19,4 @@ pretty_env_logger = "0.4"
dbus = "0.8"
rand = "0.7"
failure = "0.1"
gtk-macros = "0.2"
use super::config;
use super::utils;
use super::window::Window;
use gio::prelude::*;
......@@ -37,20 +36,18 @@ impl Application {
fn setup_gactions(&self) {
// Quit
utils::action(
&self.app,
action!(
self.app,
"quit",
None,
clone!(@strong self.app as app => move |_, _| {
app.quit();
}),
})
);
// About
utils::action(
&self.app,
action!(
self.app,
"about",
None,
clone!(@weak self.window.widget as window => move |_, _| {
let builder = gtk::Builder::new_from_resource("/org/gnome/design/Contrast/about_dialog.ui");
get_widget!(builder, gtk::AboutDialog, about_dialog);
......@@ -58,7 +55,7 @@ impl Application {
about_dialog.connect_response(|dialog, _| dialog.destroy());
about_dialog.show();
}),
})
);
// Accels
......
use crate::application::Action;
use dbus::{
blocking::{BlockingSender, Connection},
message::Message,
};
use sass_rs::{compile_string, Options};
use std::collections::HashMap;
use std::thread;
use std::time::Duration;
pub fn calc_contrast_level(bg_color: &gdk::RGBA, fg_color: &gdk::RGBA) -> f64 {
let bg_luminance = get_luminance(bg_color);
let fg_luminance = get_luminance(fg_color);
......@@ -32,3 +42,80 @@ fn to_hex(n: f64) -> String {
s
}
}
#[derive(Debug)]
pub enum ColorPickerError {
DBus(dbus::Error),
NoResponse,
}
impl From<dbus::Error> for ColorPickerError {
fn from(s: dbus::Error) -> ColorPickerError {
ColorPickerError::DBus(s)
}
}
impl From<String> for ColorPickerError {
fn from(_s: String) -> ColorPickerError {
ColorPickerError::NoResponse
}
}
impl std::fmt::Display for ColorPickerError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "failed to pick a color")
}
}
impl std::error::Error for ColorPickerError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
// Generic error, underlying cause isn't tracked.
None
}
}
pub fn pick_color() -> Result<gdk::RGBA, ColorPickerError> {
let connection = Connection::new_session()?;
let message = Message::new_method_call("org.gnome.Shell.Screenshot", "/org/gnome/Shell/Screenshot", "org.gnome.Shell.Screenshot", "PickColor")?;
let response = connection.send_with_reply_and_block(message, Duration::from_secs(60))?;
let result: HashMap<String, dbus::arg::Variant<Box<dyn dbus::arg::RefArg>>> = response.get1().ok_or_else(|| ColorPickerError::NoResponse)?;
let mut color = result
.get("color")
.ok_or_else(|| ColorPickerError::NoResponse)?
.0
.as_iter()
.ok_or_else(|| ColorPickerError::NoResponse)?;
let red = color.next().ok_or_else(|| ColorPickerError::NoResponse)?.as_f64().ok_or_else(|| ColorPickerError::NoResponse)?;
let green = color.next().ok_or_else(|| ColorPickerError::NoResponse)?.as_f64().ok_or_else(|| ColorPickerError::NoResponse)?;
let blue = color.next().ok_or_else(|| ColorPickerError::NoResponse)?.as_f64().ok_or_else(|| ColorPickerError::NoResponse)?;
let rgba = gdk::RGBA { red, green, blue, alpha: 1.0 };
Ok(rgba)
}
pub fn compile_styles(sender: &glib::Sender<Action>, fg: gdk::RGBA, bg: gdk::RGBA) {
thread::spawn(clone!(@strong sender => move || {
let colours = format!(include_str!("Adwaita/_colors.scss"), fg = fg.to_string(), bg = bg.to_string());
let colours_public = include_str!("Adwaita/_colors-public.scss");
let common = include_str!("Adwaita/_common.scss");
let drawing = include_str!("Adwaita/_drawing.scss");
let use_light = get_luminance(&bg) > 160.0 / 255.0;
let variant = if use_light { "light" } else { "dark" };
let mut scss = format!("$variant: '{}'; {} {} {} {}", variant, colours, drawing, common, colours_public);
scss.push_str(&format!("@define-color background_color {};", bg.to_string()));
scss.push_str(&format!("@define-color foreground_color {};", fg.to_string()));
match compile_string(&scss, Options::default()) {
Ok(styles) => {
if let Err(err) = sender.send(Action::ApplyStylesheet(styles)) {
error!("Can't update styles! {}", err);
}
}
Err(why) => error!("Couldn't parse the stylesheet: {}", why),
}
}));
}
use super::colour;
use super::colour_popover::ColourPopover;
use super::utils;
use gtk::prelude::*;
use gtk::Inhibit;
use std::str::FromStr;
#[derive(Clone)]
......@@ -53,15 +53,14 @@ impl ColourEntry {
}));
colour_popover.color_chooser.connect_button_press_event(clone!(@strong colour_popover, @weak self.entry as entry =>
@default-return gtk::Inhibit(false), move |_, _| {
@default-return Inhibit(false), move |_, _| {
let colour = colour_popover.color_chooser.get_rgba();
let hex_colour = colour::rgba_to_hex(&colour);
entry.set_text(&hex_colour);
colour_popover.widget.popdown();
gtk::Inhibit(false)
Inhibit(false)
}));
self.widget.pack_start(&self.entry, false, false, 0);
let colour_selector = gtk::Button::new();
......@@ -72,7 +71,7 @@ impl ColourEntry {
self.widget.pack_start(&colour_selector, false, false, 0);
colour_selector.connect_clicked(clone!(@weak self.entry as entry => move |_| {
match utils::pick_color() {
match colour::pick_color() {
Ok(rgba) => entry.set_text(&colour::rgba_to_hex(&rgba)),
Err(_) => warn!("Failed to pick a color"),
}
......
......@@ -3,10 +3,10 @@ extern crate pretty_env_logger;
extern crate log;
#[macro_use]
extern crate glib;
#[macro_use]
extern crate gtk_macros;
use gettextrs::*;
#[macro_use]
mod utils;
mod application;
mod colour;
......
......@@ -45,7 +45,6 @@ sources = files(
'contrast_preview.rs',
'main.rs',
'static_resources.rs',
'utils.rs',
'window.rs',
'window_state.rs',
)
......
use crate::application::Action;
use crate::colour;
use dbus::{
blocking::{BlockingSender, Connection},
message::Message,
};
use sass_rs::{compile_string, Options};
use std::collections::HashMap;
use std::thread;
use std::time::Duration;
macro_rules! get_widget {
($builder:expr, $wtype:ty, $name:ident) => {
let $name: $wtype = $builder.get_object(stringify!($name)).expect(&format!("Could not find widget \"{}\"", stringify!($name)));
};
}
pub fn action<T, F>(thing: &T, name: &str, value: Option<&glib::VariantTy>, action: F) -> gio::SimpleAction
where
T: gio::ActionMapExt,
for<'r, 's> F: Fn(&'r gio::SimpleAction, Option<&glib::Variant>) + 'static,
{
// Create a stateless, parameterless action
let act = gio::SimpleAction::new(name, value);
// Connect the handler
act.connect_activate(action);
// Add it to the map
thing.add_action(&act);
act
}
#[derive(Debug)]
pub enum ColorPickerError {
DBus(dbus::Error),
NoResponse,
}
impl From<dbus::Error> for ColorPickerError {
fn from(s: dbus::Error) -> ColorPickerError {
ColorPickerError::DBus(s)
}
}
impl From<String> for ColorPickerError {
fn from(_s: String) -> ColorPickerError {
ColorPickerError::NoResponse
}
}
impl std::fmt::Display for ColorPickerError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "failed to pick a color")
}
}
impl std::error::Error for ColorPickerError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
// Generic error, underlying cause isn't tracked.
None
}
}
pub fn pick_color() -> Result<gdk::RGBA, ColorPickerError> {
let connection = Connection::new_session()?;
let message = Message::new_method_call("org.gnome.Shell.Screenshot", "/org/gnome/Shell/Screenshot", "org.gnome.Shell.Screenshot", "PickColor")?;
let response = connection.send_with_reply_and_block(message, Duration::from_secs(60))?;
let result: HashMap<String, dbus::arg::Variant<Box<dyn dbus::arg::RefArg>>> = response.get1().ok_or_else(|| ColorPickerError::NoResponse)?;
let mut color = result
.get("color")
.ok_or_else(|| ColorPickerError::NoResponse)?
.0
.as_iter()
.ok_or_else(|| ColorPickerError::NoResponse)?;
let red = color.next().ok_or_else(|| ColorPickerError::NoResponse)?.as_f64().ok_or_else(|| ColorPickerError::NoResponse)?;
let green = color.next().ok_or_else(|| ColorPickerError::NoResponse)?.as_f64().ok_or_else(|| ColorPickerError::NoResponse)?;
let blue = color.next().ok_or_else(|| ColorPickerError::NoResponse)?.as_f64().ok_or_else(|| ColorPickerError::NoResponse)?;
let rgba = gdk::RGBA { red, green, blue, alpha: 1.0 };
Ok(rgba)
}
pub fn compile_styles(sender: &glib::Sender<Action>, fg: gdk::RGBA, bg: gdk::RGBA) {
thread::spawn(clone!(@strong sender => move || {
let colours = format!(include_str!("Adwaita/_colors.scss"), fg = fg.to_string(), bg = bg.to_string());
let colours_public = include_str!("Adwaita/_colors-public.scss");
let common = include_str!("Adwaita/_common.scss");
let drawing = include_str!("Adwaita/_drawing.scss");
let use_light = colour::get_luminance(&bg) > 160.0 / 255.0;
let variant = if use_light { "light" } else { "dark" };
let mut scss = format!("$variant: '{}'; {} {} {} {}", variant, colours, drawing, common, colours_public);
scss.push_str(&format!("@define-color background_color {};", bg.to_string()));
scss.push_str(&format!("@define-color foreground_color {};", fg.to_string()));
match compile_string(&scss, Options::default()) {
Ok(styles) => {
if let Err(err) = sender.send(Action::ApplyStylesheet(styles)) {
error!("Can't update styles! {}", err);
}
}
Err(why) => error!("Couldn't parse the stylesheet: {}", why),
}
}));
}
......@@ -4,10 +4,10 @@ use super::colour_entry::ColourEntry;
use super::config::{APP_ID, PROFILE};
use super::contrast_level::ContrastLevelBar;
use super::contrast_preview::ContrastPreview;
use super::utils;
use super::window_state::WindowState;
use gettextrs::gettext;
use gio::prelude::*;
use glib::ObjectExt;
use gtk::prelude::*;
use libhandy::HeaderBarExt;
......@@ -66,7 +66,7 @@ impl Window {
self.levelbar.borrow_mut().set_contrast_level(contrast_level);
self.preview.borrow_mut().set_contrast_level(contrast_level);
utils::compile_styles(&self.sender, fg_rgba, bg_rgba);
colour::compile_styles(&self.sender, fg_rgba, bg_rgba);
}
fn setup_signals(&self, window: Rc<Self>) {
......@@ -91,10 +91,9 @@ impl Window {
let fg_handle = self.fg_entry.entry.connect_changed(on_entry_changed);
let actions = gio::SimpleActionGroup::new();
utils::action(
&actions,
action!(
actions,
"reverse-colors",
None,
clone!(@strong self.fg_entry as fg_entry, @strong self.bg_entry as bg_entry => move |_, _| {
fg_entry.entry.block_signal(&fg_handle);
bg_entry.entry.block_signal(&bg_handle);
......@@ -107,7 +106,7 @@ impl Window {
bg_entry.entry.unblock_signal(&bg_handle);
window.colour_changed(fg_colour, bg_colour);
}),
})
);
self.widget.insert_action_group("window", Some(&actions));
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment