Merge pull request #63 from christopher-l/feature/headerbar-title
Show filename and dir in header bar
This commit is contained in:
commit
14bd3d3515
@ -48,6 +48,7 @@ mod popup_menu;
|
|||||||
mod project;
|
mod project;
|
||||||
mod tabline;
|
mod tabline;
|
||||||
mod error;
|
mod error;
|
||||||
|
mod subscriptions;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -83,6 +83,12 @@ impl NvimHandler {
|
|||||||
error!("Unsupported event {:?}", params);
|
error!("Unsupported event {:?}", params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"subscription" => {
|
||||||
|
self.safe_call(move |ui| {
|
||||||
|
let ui = &ui.borrow();
|
||||||
|
ui.notify(params)
|
||||||
|
});
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
error!("Notification {}({:?})", method, params);
|
error!("Notification {}({:?})", method, params);
|
||||||
}
|
}
|
||||||
@ -130,7 +136,7 @@ impl NvimHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn safe_call<F>(&self, cb: F)
|
fn safe_call<F>(&self, cb: F)
|
||||||
where
|
where
|
||||||
F: FnOnce(&Arc<UiMutex<shell::State>>) -> result::Result<(), String> + 'static + Send,
|
F: FnOnce(&Arc<UiMutex<shell::State>>) -> result::Result<(), String> + 'static + Send,
|
||||||
|
@ -59,7 +59,7 @@ pub struct Projects {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Projects {
|
impl Projects {
|
||||||
pub fn new(ref_widget: >k::ToolButton, shell: Rc<RefCell<Shell>>) -> Rc<RefCell<Projects>> {
|
pub fn new(ref_widget: >k::Button, shell: Rc<RefCell<Shell>>) -> Rc<RefCell<Projects>> {
|
||||||
let projects = Projects {
|
let projects = Projects {
|
||||||
shell,
|
shell,
|
||||||
popup: Popover::new(Some(ref_widget)),
|
popup: Popover::new(Some(ref_widget)),
|
||||||
|
39
src/shell.rs
39
src/shell.rs
@ -33,6 +33,7 @@ use error;
|
|||||||
use mode;
|
use mode;
|
||||||
use render;
|
use render;
|
||||||
use render::CellMetrics;
|
use render::CellMetrics;
|
||||||
|
use subscriptions::{SubscriptionHandle, Subscriptions};
|
||||||
|
|
||||||
const DEFAULT_FONT_NAME: &str = "DejaVu Sans Mono 12";
|
const DEFAULT_FONT_NAME: &str = "DejaVu Sans Mono 12";
|
||||||
pub const MINIMUM_SUPPORTED_NVIM_VERSION: &str = "0.2.2";
|
pub const MINIMUM_SUPPORTED_NVIM_VERSION: &str = "0.2.2";
|
||||||
@ -78,6 +79,8 @@ pub struct State {
|
|||||||
|
|
||||||
detach_cb: Option<Box<RefCell<FnMut() + Send + 'static>>>,
|
detach_cb: Option<Box<RefCell<FnMut() + Send + 'static>>>,
|
||||||
nvim_started_cb: Option<Box<RefCell<FnMut() + Send + 'static>>>,
|
nvim_started_cb: Option<Box<RefCell<FnMut() + Send + 'static>>>,
|
||||||
|
|
||||||
|
subscriptions: RefCell<Subscriptions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
@ -116,6 +119,8 @@ impl State {
|
|||||||
|
|
||||||
detach_cb: None,
|
detach_cb: None,
|
||||||
nvim_started_cb: None,
|
nvim_started_cb: None,
|
||||||
|
|
||||||
|
subscriptions: RefCell::new(Subscriptions::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,6 +333,31 @@ impl State {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn subscribe<F>(&self, event_name: &str, args: &[&str], cb: F) -> SubscriptionHandle
|
||||||
|
where
|
||||||
|
F: Fn(Vec<String>) + 'static,
|
||||||
|
{
|
||||||
|
self.subscriptions
|
||||||
|
.borrow_mut()
|
||||||
|
.subscribe(event_name, args, cb)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_autocmds(&self) {
|
||||||
|
self.subscriptions
|
||||||
|
.borrow()
|
||||||
|
.set_autocmds(&mut self.nvim().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn notify(&self, params: Vec<Value>) -> Result<(), String> {
|
||||||
|
self.subscriptions.borrow().notify(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_now(&self, handle: &SubscriptionHandle) {
|
||||||
|
self.subscriptions
|
||||||
|
.borrow()
|
||||||
|
.run_now(handle, &mut self.nvim().unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UiState {
|
pub struct UiState {
|
||||||
@ -574,6 +604,15 @@ impl Shell {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_tab(&self) {
|
||||||
|
let state = self.state.borrow();
|
||||||
|
|
||||||
|
let nvim = state.nvim();
|
||||||
|
if let Some(mut nvim) = nvim {
|
||||||
|
nvim.command(":tabe").report_err();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_detach_cb<F>(&self, cb: Option<F>)
|
pub fn set_detach_cb<F>(&self, cb: Option<F>)
|
||||||
where
|
where
|
||||||
F: FnMut() + Send + 'static,
|
F: FnMut() + Send + 'static,
|
||||||
|
157
src/subscriptions.rs
Normal file
157
src/subscriptions.rs
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use neovim_lib::{NeovimApi, Value};
|
||||||
|
|
||||||
|
use nvim::NeovimRef;
|
||||||
|
|
||||||
|
/// A subscription to a Neovim autocmd event.
|
||||||
|
struct Subscription {
|
||||||
|
/// A callback to be executed each time the event triggers.
|
||||||
|
cb: Box<Fn(Vec<String>) + 'static>,
|
||||||
|
/// A list of expressions which will be evaluated when the event triggers. The result is passed
|
||||||
|
/// to the callback.
|
||||||
|
args: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A map of all registered subscriptions.
|
||||||
|
pub struct Subscriptions(HashMap<String, Vec<Subscription>>);
|
||||||
|
|
||||||
|
/// A handle to identify a `Subscription` within the `Subscriptions` map.
|
||||||
|
///
|
||||||
|
/// Can be used to trigger the subscription manually even when the event was not triggered.
|
||||||
|
///
|
||||||
|
/// Could be used in the future to suspend individual subscriptions.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SubscriptionHandle {
|
||||||
|
event_name: String,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Subscriptions {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Subscriptions(HashMap::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Subscribe to a Neovim autocmd event.
|
||||||
|
///
|
||||||
|
/// Subscriptions are not active immediately but only after `set_autocmds` is called. At the
|
||||||
|
/// moment, all calls to `subscribe` must be made before calling `set_autocmds`.
|
||||||
|
///
|
||||||
|
/// This function is wrapped by `shell::State`.
|
||||||
|
///
|
||||||
|
/// # Arguments:
|
||||||
|
///
|
||||||
|
/// - `event_name`: The event to register.
|
||||||
|
/// See `:help autocmd-events` for a list of supported event names. Event names can be
|
||||||
|
/// comma-separated.
|
||||||
|
///
|
||||||
|
/// - `args`: A list of expressions to be evaluated when the event triggers.
|
||||||
|
/// Expressions are evaluated using Vimscript. The results are passed to the callback as a
|
||||||
|
/// list of Strings.
|
||||||
|
/// This is especially useful as `Neovim::eval` is synchronous and might block if called from
|
||||||
|
/// the callback function; so always use the `args` mechanism instead.
|
||||||
|
///
|
||||||
|
/// - `cb`: The callback function.
|
||||||
|
/// This will be called each time the event triggers or when `run_now` is called.
|
||||||
|
/// It is passed a vector with the results of the evaluated expressions given with `args`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// Call a function each time a buffer is entered or the current working directory is changed.
|
||||||
|
/// Pass the current buffer name and directory to the callback.
|
||||||
|
/// ```
|
||||||
|
/// let my_subscription = shell.state.borrow()
|
||||||
|
/// .subscribe("BufEnter,DirChanged", &["expand(@%)", "getcwd()"], move |args| {
|
||||||
|
/// let filename = &args[0];
|
||||||
|
/// let dir = &args[1];
|
||||||
|
/// // do stuff
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
pub fn subscribe<F>(&mut self, event_name: &str, args: &[&str], cb: F) -> SubscriptionHandle
|
||||||
|
where
|
||||||
|
F: Fn(Vec<String>) + 'static,
|
||||||
|
{
|
||||||
|
let entry = self.0.entry(event_name.to_owned()).or_insert(Vec::new());
|
||||||
|
let index = entry.len();
|
||||||
|
entry.push(Subscription {
|
||||||
|
cb: Box::new(cb),
|
||||||
|
args: args.into_iter().map(|&s| s.to_owned()).collect(),
|
||||||
|
});
|
||||||
|
SubscriptionHandle {
|
||||||
|
event_name: event_name.to_owned(),
|
||||||
|
index,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Register all subscriptions with Neovim.
|
||||||
|
///
|
||||||
|
/// This function is wrapped by `shell::State`.
|
||||||
|
pub fn set_autocmds(&self, nvim: &mut NeovimRef) {
|
||||||
|
for (event_name, subscriptions) in &self.0 {
|
||||||
|
for (i, subscription) in subscriptions.iter().enumerate() {
|
||||||
|
let args = subscription
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.fold("".to_owned(), |acc, arg| acc + ", " + &arg);
|
||||||
|
nvim.command(&format!(
|
||||||
|
"au {} * call rpcnotify(1, 'subscription', '{}', {} {})",
|
||||||
|
event_name, event_name, i, args,
|
||||||
|
)).unwrap_or_else(|err| {
|
||||||
|
error!("Could not set autocmd: {}", err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trigger given event.
|
||||||
|
fn on_notify(&self, event_name: &str, index: usize, args: Vec<String>) {
|
||||||
|
if let Some(subscription) = self.0.get(event_name).and_then(|v| v.get(index)) {
|
||||||
|
(*subscription.cb)(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper around `on_notify` for easy calling with a `neovim_lib::Handler` implementation.
|
||||||
|
///
|
||||||
|
/// This function is wrapped by `shell::State`.
|
||||||
|
pub fn notify(&self, params: Vec<Value>) -> Result<(), String> {
|
||||||
|
let mut params_iter = params.into_iter();
|
||||||
|
let ev_name = params_iter.next();
|
||||||
|
let ev_name = ev_name
|
||||||
|
.as_ref()
|
||||||
|
.and_then(Value::as_str)
|
||||||
|
.ok_or("Error reading event name")?;
|
||||||
|
let index = params_iter
|
||||||
|
.next()
|
||||||
|
.and_then(|i| i.as_u64())
|
||||||
|
.ok_or("Error reading index")? as usize;
|
||||||
|
let args = params_iter
|
||||||
|
.map(|arg| arg.as_str().map(|s| s.to_owned()))
|
||||||
|
.collect::<Option<Vec<String>>>()
|
||||||
|
.ok_or("Error reading args")?;
|
||||||
|
self.on_notify(ev_name, index, args);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Manually trigger the given subscription.
|
||||||
|
///
|
||||||
|
/// The `nvim` instance is needed to evaluate the `args` expressions.
|
||||||
|
///
|
||||||
|
/// This function is wrapped by `shell::State`.
|
||||||
|
pub fn run_now(&self, handle: &SubscriptionHandle, nvim: &mut NeovimRef) {
|
||||||
|
let subscription = &self.0.get(&handle.event_name).unwrap()[handle.index];
|
||||||
|
let args = subscription
|
||||||
|
.args
|
||||||
|
.iter()
|
||||||
|
.map(|arg| nvim.eval(arg))
|
||||||
|
.map(|res| {
|
||||||
|
res.ok()
|
||||||
|
.and_then(|val| val.as_str().map(|s: &str| s.to_owned()))
|
||||||
|
})
|
||||||
|
.collect::<Option<Vec<String>>>();
|
||||||
|
if let Some(args) = args {
|
||||||
|
self.on_notify(&handle.event_name, handle.index, args);
|
||||||
|
} else {
|
||||||
|
error!("Error manually running {:?}", handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
160
src/ui.rs
160
src/ui.rs
@ -1,13 +1,13 @@
|
|||||||
use std::cell::{Ref, RefCell, RefMut};
|
use std::cell::{Ref, RefCell, RefMut};
|
||||||
use std::{env, thread};
|
use std::{env, thread};
|
||||||
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use gdk;
|
use gdk;
|
||||||
use gtk;
|
use gtk;
|
||||||
use gtk_sys;
|
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{AboutDialog, ApplicationWindow, HeaderBar, Image, SettingsExt, ToolButton};
|
use gtk::{AboutDialog, ApplicationWindow, Button, HeaderBar, SettingsExt};
|
||||||
use gio::prelude::*;
|
use gio::prelude::*;
|
||||||
use gio::{Menu, MenuExt, MenuItem, SimpleAction};
|
use gio::{Menu, MenuExt, MenuItem, SimpleAction};
|
||||||
use toml;
|
use toml;
|
||||||
@ -17,6 +17,7 @@ use shell::{self, Shell, ShellOptions};
|
|||||||
use shell_dlg;
|
use shell_dlg;
|
||||||
use project::Projects;
|
use project::Projects;
|
||||||
use plug_manager;
|
use plug_manager;
|
||||||
|
use subscriptions::SubscriptionHandle;
|
||||||
|
|
||||||
macro_rules! clone {
|
macro_rules! clone {
|
||||||
(@param _) => ( _ );
|
(@param _) => ( _ );
|
||||||
@ -50,16 +51,24 @@ pub struct Ui {
|
|||||||
pub struct Components {
|
pub struct Components {
|
||||||
window: Option<ApplicationWindow>,
|
window: Option<ApplicationWindow>,
|
||||||
window_state: WindowState,
|
window_state: WindowState,
|
||||||
open_btn: ToolButton,
|
open_btn: Button,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Components {
|
impl Components {
|
||||||
fn new() -> Components {
|
fn new() -> Components {
|
||||||
let save_image =
|
let open_btn = Button::new();
|
||||||
Image::new_from_icon_name("document-open", gtk_sys::GTK_ICON_SIZE_SMALL_TOOLBAR as i32);
|
let open_btn_box = gtk::Box::new(gtk::Orientation::Horizontal, 3);
|
||||||
|
open_btn_box.pack_start(>k::Label::new("Open"), false, false, 3);
|
||||||
|
open_btn_box.pack_start(
|
||||||
|
>k::Image::new_from_icon_name("pan-down-symbolic", gtk::IconSize::Menu.into()),
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
3,
|
||||||
|
);
|
||||||
|
open_btn.add(&open_btn_box);
|
||||||
|
open_btn.set_can_focus(false);
|
||||||
Components {
|
Components {
|
||||||
open_btn: ToolButton::new(Some(&save_image), "Open"),
|
open_btn,
|
||||||
window: None,
|
window: None,
|
||||||
window_state: WindowState::load(),
|
window_state: WindowState::load(),
|
||||||
}
|
}
|
||||||
@ -126,48 +135,6 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, &window);
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
|
|
||||||
if restore_win_state {
|
if restore_win_state {
|
||||||
if comps.window_state.is_maximized {
|
if comps.window_state.is_maximized {
|
||||||
window.maximize();
|
window.maximize();
|
||||||
@ -182,6 +149,21 @@ impl Ui {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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, &window);
|
||||||
|
}
|
||||||
|
|
||||||
|
let update_subtitle = if use_header_bar {
|
||||||
|
Some(self.create_header_bar())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let comps_ref = self.comps.clone();
|
let comps_ref = self.comps.clone();
|
||||||
window.connect_size_allocate(move |window, _| {
|
window.connect_size_allocate(move |window, _| {
|
||||||
gtk_window_size_allocate(window, &mut *comps_ref.borrow_mut())
|
gtk_window_size_allocate(window, &mut *comps_ref.borrow_mut())
|
||||||
@ -202,7 +184,30 @@ impl Ui {
|
|||||||
window.add(&**shell);
|
window.add(&**shell);
|
||||||
|
|
||||||
window.show_all();
|
window.show_all();
|
||||||
window.set_title("NeovimGtk");
|
|
||||||
|
let comps_ref = self.comps.clone();
|
||||||
|
let update_title = shell.state.borrow().subscribe(
|
||||||
|
"BufEnter,DirChanged",
|
||||||
|
&["expand('%:p')", "getcwd()"],
|
||||||
|
move |args| {
|
||||||
|
let comps = comps_ref.borrow();
|
||||||
|
let window = comps.window.as_ref().unwrap();
|
||||||
|
let file_path = &args[0];
|
||||||
|
let dir = Path::new(&args[1]);
|
||||||
|
let filename = if file_path.is_empty() {
|
||||||
|
"[No Name]"
|
||||||
|
} else if let Some(rel_path) = Path::new(&file_path)
|
||||||
|
.strip_prefix(&dir)
|
||||||
|
.ok()
|
||||||
|
.and_then(|p| p.to_str())
|
||||||
|
{
|
||||||
|
rel_path
|
||||||
|
} else {
|
||||||
|
&file_path
|
||||||
|
};
|
||||||
|
window.set_title(filename);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let comps_ref = self.comps.clone();
|
let comps_ref = self.comps.clone();
|
||||||
let shell_ref = self.shell.clone();
|
let shell_ref = self.shell.clone();
|
||||||
@ -222,12 +227,67 @@ 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 || {
|
||||||
|
let state = state_ref.borrow();
|
||||||
plug_manager_ref
|
plug_manager_ref
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.init_nvim_client(state_ref.borrow().nvim_clone());
|
.init_nvim_client(state_ref.borrow().nvim_clone());
|
||||||
|
state.set_autocmds();
|
||||||
|
state.run_now(&update_title);
|
||||||
|
if let Some(ref update_subtitle) = update_subtitle {
|
||||||
|
state.run_now(&update_subtitle);
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_header_bar(&self) -> SubscriptionHandle {
|
||||||
|
let header_bar = HeaderBar::new();
|
||||||
|
let comps = self.comps.borrow();
|
||||||
|
let window = comps.window.as_ref().unwrap();
|
||||||
|
|
||||||
|
let projects = self.projects.clone();
|
||||||
|
header_bar.pack_start(&comps.open_btn);
|
||||||
|
comps
|
||||||
|
.open_btn
|
||||||
|
.connect_clicked(move |_| projects.borrow_mut().show());
|
||||||
|
|
||||||
|
let new_tab_btn =
|
||||||
|
Button::new_from_icon_name("tab-new-symbolic", gtk::IconSize::SmallToolbar.into());
|
||||||
|
let shell_ref = Rc::clone(&self.shell);
|
||||||
|
new_tab_btn.connect_clicked(move |_| shell_ref.borrow_mut().new_tab());
|
||||||
|
new_tab_btn.set_can_focus(false);
|
||||||
|
new_tab_btn.set_tooltip_text("Open a new tab");
|
||||||
|
header_bar.pack_start(&new_tab_btn);
|
||||||
|
|
||||||
|
let paste_btn =
|
||||||
|
Button::new_from_icon_name("edit-paste-symbolic", gtk::IconSize::SmallToolbar.into());
|
||||||
|
let shell = self.shell.clone();
|
||||||
|
paste_btn.connect_clicked(move |_| shell.borrow_mut().edit_paste());
|
||||||
|
paste_btn.set_can_focus(false);
|
||||||
|
paste_btn.set_tooltip_text("Paste from clipboard");
|
||||||
|
header_bar.pack_end(&paste_btn);
|
||||||
|
|
||||||
|
let save_btn = Button::new_with_label("Save All");
|
||||||
|
let shell = self.shell.clone();
|
||||||
|
save_btn.connect_clicked(move |_| shell.borrow_mut().edit_save_all());
|
||||||
|
save_btn.set_can_focus(false);
|
||||||
|
header_bar.pack_end(&save_btn);
|
||||||
|
|
||||||
|
header_bar.set_show_close_button(true);
|
||||||
|
|
||||||
|
window.set_titlebar(Some(&header_bar));
|
||||||
|
|
||||||
|
let shell = self.shell.borrow();
|
||||||
|
let update_subtitle = shell.state.borrow().subscribe(
|
||||||
|
"DirChanged",
|
||||||
|
&["getcwd()"],
|
||||||
|
move |args| {
|
||||||
|
header_bar.set_subtitle(&*args[0]);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
update_subtitle
|
||||||
|
}
|
||||||
|
|
||||||
fn create_main_menu(&self, app: >k::Application, window: >k::ApplicationWindow) {
|
fn create_main_menu(&self, app: >k::Application, window: >k::ApplicationWindow) {
|
||||||
let plug_manager = self.plug_manager.clone();
|
let plug_manager = self.plug_manager.clone();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user