Skip to content

Instantly share code, notes, and snippets.

@koji-m
Last active November 25, 2017 03:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koji-m/8f19159bbcab3b1fa3704972375d08f0 to your computer and use it in GitHub Desktop.
Save koji-m/8f19159bbcab3b1fa3704972375d08f0 to your computer and use it in GitHub Desktop.
Vanilla Text version 0.0.2
//main.rs ver 0.0.2
extern crate gtk;
extern crate gio;
extern crate gdk;
extern crate gdk_pixbuf;
mod win;
use std::env::Args;
use std::rc::Rc;
use std::cell::RefCell;
use gtk::{
WidgetExt, WindowExt,
GtkApplicationExt, AboutDialogExt,
DialogExt, FileChooserExt,
};
use gio::{
ApplicationExt, ApplicationExtManual, MenuExt,
ActionMapExt, SimpleActionExt
};
use win::{
Window, WindowExtend, Windows, WindowsExtend
};
fn init_actions(app: &gtk::Application, wins: &Windows) {
let new_action = gio::SimpleAction::new("new", None);
{
let app = app.clone();
let wins = wins.clone();
new_action.connect_activate(move |_, _| {
let w = Window::create(&app, wins.clone());
w.init();
});
}
let open_action = gio::SimpleAction::new("open", None);
{
let app = app.clone();
let wins = wins.clone();
open_action.connect_activate(move |_, _| {
if let Some(file) = open_file_chooser_run() {
if let Some(win) = wins.get_window(&file) {
win.window().present();
} else if let Some(win) = wins.get_empty_window() {
win.load_file(&file);
win.window().present();
} else {
let win = wins.open(&file, &app);
win.window().present();
}
}
});
}
let quit_action = gio::SimpleAction::new("quit", None);
{
let app = app.clone();
quit_action.connect_activate(move |_, _| {
app.quit();
});
}
let about_action = gio::SimpleAction::new("about", None);
about_action.connect_activate(move |_, _| {
show_about();
});
app.add_action(&new_action);
app.add_action(&open_action);
app.add_action(&quit_action);
app.add_action(&about_action);
}
fn open_file_chooser_run() -> Option<gio::File> {
let dialog = gtk::FileChooserDialog::new::<gtk::Window>(Some("Open File"),
None,
gtk::FileChooserAction::Open);
dialog.add_button("Cancel", gtk::ResponseType::Cancel.into());
dialog.add_button("Open", gtk::ResponseType::Accept.into());
let file;
if dialog.run() == gtk::ResponseType::Accept.into() {
if let Some(path) = dialog.get_filename() {
file = Some(gio::File::new_for_path(path.as_path()))
} else {
file = None
}
} else {
file = None
}
dialog.destroy();
file
}
fn show_about() {
let dialog = gtk::AboutDialog::new();
dialog.set_program_name("Vanilla Text");
let logo = gdk_pixbuf::Pixbuf::new_from_file("assets/logo.png");
if let Ok(logo) = logo {
dialog.set_logo(Some(&logo));
}
dialog.run();
dialog.destroy();
}
fn init_accels(app: &gtk::Application) {
app.add_accelerator("<Ctrl>q", "app.quit", None);
app.add_accelerator("<Ctrl>n", "app.new", None);
app.add_accelerator("<Ctrl>o", "app.open", None);
app.add_accelerator("<Ctrl>s", "win.save", None);
app.add_accelerator("<Shift><Ctrl>s", "win.saveas", None);
app.add_accelerator("<Ctrl>w", "win.close", None);
app.add_accelerator("<Ctrl>a", "win.selectall", None);
app.add_accelerator("<Ctrl>c", "win.copy", None);
app.add_accelerator("<Ctrl>v", "win.paste", None);
app.add_accelerator("<Ctrl>x", "win.cut", None);
}
fn app_menu() -> gio::Menu {
use gio::MenuItem;
let app_menu = gio::Menu::new();
let newfile = MenuItem::new("New", "app.new");
let open = MenuItem::new("Open", "app.open");
let about = MenuItem::new("About", "app.about");
let quit = MenuItem::new("Quit", "app.quit");
app_menu.append_item(&newfile);
app_menu.append_item(&open);
app_menu.append_item(&about);
app_menu.append_item(&quit);
app_menu
}
fn menu_bar() -> gio::Menu {
use gio::{Menu, MenuItem};
let menu_bar = Menu::new();
let submenu_file = Menu::new();
let save = MenuItem::new("Save", "win.save");
let saveas = MenuItem::new("Save as...", "win.saveas");
let close = MenuItem::new("Close", "win.close");
submenu_file.append_item(&save);
submenu_file.append_item(&saveas);
submenu_file.append_item(&close);
let submenu_edit = Menu::new();
let cut = MenuItem::new("Cut", "win.cut");
let copy = MenuItem::new("Copy", "win.copy");
let paste = MenuItem::new("Paste", "win.paste");
let selectall = MenuItem::new("Select All", "win.selectall");
submenu_edit.append_item(&cut);
submenu_edit.append_item(&copy);
submenu_edit.append_item(&paste);
submenu_edit.append_item(&selectall);
menu_bar.append_submenu("File", &submenu_file);
menu_bar.append_submenu("Edit", &submenu_edit);
menu_bar
}
pub fn run(args: Args) {
match gtk::Application::new("com.github.koji-m.vanilla_text", gio::APPLICATION_HANDLES_OPEN) {
Ok(app) => {
let wins = Rc::new(RefCell::new(Vec::<Window>::new()));
{
let wins = wins.clone();
app.connect_startup(move |app| {
init_actions(app, &wins);
init_accels(app);
app.set_app_menu(&app_menu());
app.set_menubar(&menu_bar());
});
}
{
let wins = wins.clone();
app.connect_activate(move |app| {
let w = Window::create(app, wins.clone());
w.init();
});
}
{
let wins = wins.clone();
app.connect_open(move |app, files, _| {
for file in files {
if let Some(win) = wins.get_window(&file) {
win.window().present();
} else {
let win = wins.open(&file, &app);
win.window().present();
}
}
});
}
let args: Vec<String> = args.collect();
let argv: Vec<&str> = args.iter().map(|s| s.as_ref()).collect();
app.run(argv.as_slice());
},
Err(_) => {
println!("Application run error");
}
};
}
fn main() {
run(std::env::args());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment