nvim_gtk/
settings.rs

1use std::rc::{Rc, Weak};
2use std::cell::RefCell;
3
4use crate::shell::Shell;
5#[cfg(unix)]
6use gio;
7#[cfg(unix)]
8use gio::SettingsExt;
9
10#[derive(PartialEq)]
11pub enum FontSource {
12    Rpc,
13    #[cfg(unix)]
14    Gnome,
15    Default,
16}
17
18struct State {
19    font_source: FontSource,
20
21    #[cfg(unix)]
22    gnome_interface_settings: gio::Settings,
23}
24
25impl State {
26    #[cfg(unix)]
27    pub fn new() -> State {
28        State {
29            font_source: FontSource::Default,
30            gnome_interface_settings: gio::Settings::new("org.gnome.desktop.interface"),
31        }
32    }
33
34    #[cfg(target_os = "windows")]
35    pub fn new() -> State {
36        State { font_source: FontSource::Default }
37    }
38
39    #[cfg(unix)]
40    fn update_font(&mut self, shell: &mut Shell) {
41        // rpc is priority for font
42        if self.font_source == FontSource::Rpc {
43            return;
44        }
45
46        if let Some(ref font_name) =
47            self.gnome_interface_settings.get_string(
48                "monospace-font-name",
49            )
50        {
51            shell.set_font_desc(font_name);
52            self.font_source = FontSource::Gnome;
53        }
54    }
55}
56
57pub struct Settings {
58    shell: Option<Weak<RefCell<Shell>>>,
59    state: Rc<RefCell<State>>,
60}
61
62impl Settings {
63    pub fn new() -> Settings {
64        Settings {
65            shell: None,
66            state: Rc::new(RefCell::new(State::new())),
67        }
68    }
69
70    pub fn set_shell(&mut self, shell: Weak<RefCell<Shell>>) {
71        self.shell = Some(shell);
72    }
73
74    #[cfg(unix)]
75    pub fn init(&mut self) {
76        let shell = Weak::upgrade(self.shell.as_ref().unwrap()).unwrap();
77        let state = self.state.clone();
78        self.state.borrow_mut().update_font(
79            &mut *shell.borrow_mut(),
80        );
81        self.state
82            .borrow()
83            .gnome_interface_settings
84            .connect_changed(move |_, _| {
85                monospace_font_changed(&mut *shell.borrow_mut(), &mut *state.borrow_mut())
86            });
87    }
88
89    #[cfg(target_os = "windows")]
90    pub fn init(&mut self) {}
91
92    pub fn set_font_source(&mut self, src: FontSource) {
93        self.state.borrow_mut().font_source = src;
94    }
95}
96
97#[cfg(unix)]
98fn monospace_font_changed(mut shell: &mut Shell, state: &mut State) {
99    // rpc is priority for font
100    if state.font_source != FontSource::Rpc {
101        state.update_font(&mut shell);
102    }
103}
104
105use std::path::Path;
106use std::fs::File;
107use std::io::prelude::*;
108
109use toml;
110use serde;
111
112use crate::dirs;
113
114pub trait SettingsLoader: Sized + serde::Serialize + Default {
115    const SETTINGS_FILE: &'static str;
116
117    fn from_str(s: &str) -> Result<Self, String>;
118
119    fn load() -> Self {
120        match load_err() {
121            Ok(settings) => settings,
122            Err(e) => {
123                error!("{}", e);
124                Default::default()
125            }
126        }
127    }
128
129    fn is_file_exists() -> bool {
130        if let Ok(mut toml_path) = dirs::get_app_config_dir() {
131            toml_path.push(Self::SETTINGS_FILE);
132            toml_path.is_file()
133        } else {
134            false
135        }
136    }
137
138    fn save(&self) {
139        match save_err(self) {
140            Ok(()) => (),
141            Err(e) => error!("{}", e),
142        }
143    }
144}
145
146fn load_from_file<T: SettingsLoader>(path: &Path) -> Result<T, String> {
147    if path.exists() {
148        let mut file = File::open(path).map_err(|e| format!("{}", e))?;
149        let mut contents = String::new();
150        file.read_to_string(&mut contents).map_err(
151            |e| format!("{}", e),
152        )?;
153        T::from_str(&contents)
154    } else {
155        Ok(Default::default())
156    }
157}
158
159fn load_err<T: SettingsLoader>() -> Result<T, String> {
160    let mut toml_path = dirs::get_app_config_dir_create()?;
161    toml_path.push(T::SETTINGS_FILE);
162    load_from_file(&toml_path)
163}
164
165
166fn save_err<T: SettingsLoader>(sl: &T) -> Result<(), String> {
167    let mut toml_path = dirs::get_app_config_dir_create()?;
168    toml_path.push(T::SETTINGS_FILE);
169    let mut file = File::create(toml_path).map_err(|e| format!("{}", e))?;
170
171    let contents = toml::to_vec::<T>(sl).map_err(|e| format!("{}", e))?;
172
173    file.write_all(&contents).map_err(|e| format!("{}", e))?;
174
175    Ok(())
176}