This commit is contained in:
daa 2018-01-23 23:22:19 +03:00
parent a6e16d1cbd
commit 8a025c3a7c

192
src/ui.rs
View File

@ -1,16 +1,18 @@
use std::cell::{RefCell, Ref, RefMut}; use std::cell::{Ref, RefCell, RefMut};
use std::{env, thread}; use std::{env, thread};
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use gdk;
use gtk; use gtk;
use gtk_sys; use gtk_sys;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{ApplicationWindow, HeaderBar, ToolButton, Image, AboutDialog, SettingsExt}; use gtk::{AboutDialog, ApplicationWindow, HeaderBar, Image, SettingsExt, ToolButton};
use gio::prelude::*; use gio::prelude::*;
use gio::{Menu, MenuExt, MenuItem, SimpleAction}; use gio::{Menu, MenuExt, MenuItem, SimpleAction};
use toml;
use settings::Settings; use settings::{Settings, SettingsLoader};
use shell::{self, Shell, ShellOptions}; use shell::{self, Shell, ShellOptions};
use shell_dlg; use shell_dlg;
use project::Projects; use project::Projects;
@ -44,6 +46,7 @@ pub struct Ui {
pub struct Components { pub struct Components {
window: Option<ApplicationWindow>, window: Option<ApplicationWindow>,
window_state: WindowState,
open_btn: ToolButton, open_btn: ToolButton,
} }
@ -55,6 +58,7 @@ impl Components {
Components { Components {
open_btn: ToolButton::new(Some(&save_image), "Open"), open_btn: ToolButton::new(Some(&save_image), "Open"),
window: None, window: None,
window_state: WindowState::load(),
} }
} }
@ -98,65 +102,93 @@ impl Ui {
let mut settings = self.settings.borrow_mut(); let mut settings = self.settings.borrow_mut();
settings.init(); settings.init();
let mut comps = self.comps.borrow_mut(); let window = ApplicationWindow::new(app);
self.shell.borrow_mut().init(); {
// initialize window from comps
// borrowing of comps must be leaved
// for event processing
let mut comps = self.comps.borrow_mut();
comps.window = Some(ApplicationWindow::new(app)); self.shell.borrow_mut().init();
let window = comps.window.as_ref().unwrap();
let prefer_dark_theme = env::var("NVIM_GTK_PREFER_DARK_THEME") comps.window = Some(window.clone());
.map(|opt| opt.trim() == "1")
.unwrap_or(false); let prefer_dark_theme = env::var("NVIM_GTK_PREFER_DARK_THEME")
if prefer_dark_theme { .map(|opt| opt.trim() == "1")
if let Some(settings) = window.get_settings() { .unwrap_or(false);
settings.set_property_gtk_application_prefer_dark_theme(true); if prefer_dark_theme {
if let Some(settings) = window.get_settings() {
settings.set_property_gtk_application_prefer_dark_theme(true);
}
}
// Client side decorations including the toolbar are disabled via NVIM_GTK_NO_HEADERBAR=1
let use_header_bar = env::var("NVIM_GTK_NO_HEADERBAR")
.map(|opt| opt.trim() != "1")
.unwrap_or(true);
if app.prefers_app_menu() || use_header_bar {
self.create_main_menu(app);
}
if use_header_bar {
let header_bar = HeaderBar::new();
let projects = self.projects.clone();
header_bar.pack_start(&comps.open_btn);
comps
.open_btn
.connect_clicked(move |_| projects.borrow_mut().show());
let save_image = Image::new_from_icon_name(
"document-save",
gtk_sys::GTK_ICON_SIZE_SMALL_TOOLBAR as i32,
);
let save_btn = ToolButton::new(Some(&save_image), "Save");
let shell = self.shell.clone();
save_btn.connect_clicked(move |_| shell.borrow_mut().edit_save_all());
header_bar.pack_start(&save_btn);
let paste_image = Image::new_from_icon_name(
"edit-paste",
gtk_sys::GTK_ICON_SIZE_SMALL_TOOLBAR as i32,
);
let paste_btn = ToolButton::new(Some(&paste_image), "Paste");
let shell = self.shell.clone();
paste_btn.connect_clicked(move |_| shell.borrow_mut().edit_paste());
header_bar.pack_start(&paste_btn);
header_bar.set_show_close_button(true);
window.set_titlebar(Some(&header_bar));
}
window.set_default_size(
comps.window_state.current_width,
comps.window_state.current_height,
);
if comps.window_state.is_maximized {
window.maximize();
} }
} }
// Client side decorations including the toolbar are disabled via NVIM_GTK_NO_HEADERBAR=1 let comps_ref = self.comps.clone();
let use_header_bar = env::var("NVIM_GTK_NO_HEADERBAR") window.connect_size_allocate(move |window, _| {
.map(|opt| opt.trim() != "1") gtk_window_size_allocate(window, &mut *comps_ref.borrow_mut())
.unwrap_or(true); });
if app.prefers_app_menu() || use_header_bar { let comps_ref = self.comps.clone();
self.create_main_menu(app); window.connect_window_state_event(move |_, event| {
} gtk_window_state_event(event, &mut *comps_ref.borrow_mut());
Inhibit(false)
});
if use_header_bar { let comps_ref = self.comps.clone();
let header_bar = HeaderBar::new(); window.connect_destroy(move |_| {
comps_ref.borrow().window_state.save();
let projects = self.projects.clone(); });
header_bar.pack_start(&comps.open_btn);
comps.open_btn.connect_clicked(
move |_| projects.borrow_mut().show(),
);
let save_image = Image::new_from_icon_name(
"document-save",
gtk_sys::GTK_ICON_SIZE_SMALL_TOOLBAR as i32,
);
let save_btn = ToolButton::new(Some(&save_image), "Save");
let shell = self.shell.clone();
save_btn.connect_clicked(move |_| shell.borrow_mut().edit_save_all());
header_bar.pack_start(&save_btn);
let paste_image = Image::new_from_icon_name(
"edit-paste",
gtk_sys::GTK_ICON_SIZE_SMALL_TOOLBAR as i32,
);
let paste_btn = ToolButton::new(Some(&paste_image), "Paste");
let shell = self.shell.clone();
paste_btn.connect_clicked(move |_| shell.borrow_mut().edit_paste());
header_bar.pack_start(&paste_btn);
header_bar.set_show_close_button(true);
window.set_titlebar(Some(&header_bar));
}
window.set_default_size(800, 600);
let shell = self.shell.borrow(); let shell = self.shell.borrow();
window.add(&**shell); window.add(&**shell);
@ -182,9 +214,9 @@ impl Ui {
let state_ref = self.shell.borrow().state.clone(); let state_ref = self.shell.borrow().state.clone();
let plug_manager_ref = self.plug_manager.clone(); let plug_manager_ref = self.plug_manager.clone();
shell.set_nvim_started_cb(Some(move || { shell.set_nvim_started_cb(Some(move || {
plug_manager_ref.borrow_mut().init_nvim_client( plug_manager_ref
state_ref.borrow().nvim_clone(), .borrow_mut()
); .init_nvim_client(state_ref.borrow().nvim_clone());
})); }));
} }
@ -236,7 +268,7 @@ fn on_help_about(comps: &Components) {
about.set_comments( about.set_comments(
format!( format!(
"Build on top of neovim\n\ "Build on top of neovim\n\
Minimum supported neovim version: {}", Minimum supported neovim version: {}",
shell::MINIMUM_SUPPORTED_NVIM_VERSION shell::MINIMUM_SUPPORTED_NVIM_VERSION
).as_str(), ).as_str(),
); );
@ -260,6 +292,50 @@ fn gtk_delete(comps: &UiMutex<Components>, shell: &RefCell<Shell>) -> Inhibit {
}) })
} }
fn gtk_window_size_allocate(app_window: &gtk::ApplicationWindow, comps: &mut Components) {
if !app_window.is_maximized() {
let (current_width, current_height) = app_window.get_size();
comps.window_state.current_width = current_width;
comps.window_state.current_height = current_height;
}
}
fn gtk_window_state_event(event: &gdk::EventWindowState, comps: &mut Components) {
comps.window_state.is_maximized = event
.get_new_window_state()
.contains(gdk::WindowState::MAXIMIZED);
}
#[derive(Serialize, Deserialize)]
struct WindowState {
current_width: i32,
current_height: i32,
is_maximized: bool,
}
impl WindowState {
pub fn new() -> Self {
WindowState {
current_width: 800,
current_height: 600,
is_maximized: false,
}
}
}
impl SettingsLoader for WindowState {
const SETTINGS_FILE: &'static str = "window.toml";
fn empty() -> WindowState {
WindowState::new()
}
fn from_str(s: &str) -> Result<Self, String> {
toml::from_str(&s).map_err(|e| format!("{}", e))
}
}
pub struct UiMutex<T: ?Sized> { pub struct UiMutex<T: ?Sized> {
thread: thread::ThreadId, thread: thread::ThreadId,
data: RefCell<T>, data: RefCell<T>,