extern crate gdk;
extern crate gtk;
#[macro_use]
extern crate mg;
extern crate mg_settings;
#[macro_use]
extern crate mg_settings_macros;
extern crate pretty_env_logger;
extern crate relm;
#[macro_use]
extern crate relm_derive;
use gdk::RGBA;
use gtk::{ButtonExt, LabelExt, OrientableExt, WidgetExt};
use gtk::Orientation::Vertical;
use mg::{
Alert,
AppClose,
Color,
CustomCommand,
DarkTheme,
DeleteCompletionItem,
DialogBuilder,
Info,
Mg,
Mode,
Modes,
ModeChanged,
SetMode,
SetSetting,
SettingChanged,
StatusBarItem,
StatusBarVisible,
Title,
Variables,
Warning,
blocking_dialog,
input,
question,
};
use relm::{Relm, Widget};
use relm_derive::widget;
use AppSettingsVariant::*;
use AppCommand::*;
use Msg::*;
pub struct Model {
relm: Relm<Win>,
statusbar_visible: bool,
text: String,
title: String,
}
#[derive(Msg)]
pub enum Msg {
CheckQuit(Option<String>),
Command(AppCommand),
Echo(Option<String>),
NewMode(String),
Setting(AppSettingsVariant),
ShowAlert,
ShowBlockingInput,
ShowInfo,
ShowInput,
ShowQuestion,
ShowWarning,
ToggleStatusBar,
}
static MODES: Modes = &[
Mode { name: "foo", prefix: "f", show_count: true },
Mode { name: "insert", prefix: "i", show_count: false },
];
#[widget]
impl Widget for Win {
fn init_view(&mut self) {
self.widgets.entry.grab_focus();
}
fn model(relm: &Relm<Self>, _model: ()) -> Model {
Model {
relm: relm.clone(),
statusbar_visible: true,
text: "Mg App".to_string(),
title: "First Mg Program".to_string(),
}
}
fn mode_changed(&mut self, mode: &str) {
if mode != "normal" {
self.model.text = format!("Title was: {}", self.model.title);
self.streams.mg.emit(SetSetting(WindowTitle(mode.to_string())));
}
}
fn setting_changed(&mut self, setting: AppSettingsVariant) {
match setting {
CustomSet(setting) => self.model.text = format!("custom setting is: {:?}", setting),
WindowTitle(title) => self.model.title = title,
TitleLen(len) => self.model.title = format!("New title len: {}", len),
Boolean(_) | Width(_) => println!("boolean or width"),
}
}
fn update(&mut self, event: Msg) {
match event {
CheckQuit(answer) => {
if answer == Some("y".to_string()) {
gtk::main_quit();
}
},
Command(command) => {
match command {
BackwardSearch(input) => println!("Searching backward for {}", input),
DeleteEntry => self.streams.mg.emit(DeleteCompletionItem),
Follow => (),
Insert | Normal => (),
Open(url) => self.model.text = format!("Opening URL {}", url),
Quit => gtk::main_quit(),
Search(input) => println!("Searching for {}", input),
ShowCount(count) => println!("Count: {:?}", count),
WinOpen(url) => self.model.text = format!("Opening URL {} in new window", url),
}
},
Echo(answer) => self.model.text = format!("You said: {}", answer.unwrap_or("Nothing".to_string())),
NewMode(mode) => self.mode_changed(&mode),
Setting(setting) => self.setting_changed(setting),
ShowAlert => self.streams.mg.emit(Alert("Blue Alert".to_string())),
ShowBlockingInput => {
let builder = DialogBuilder::new()
.message("Do you wanto to quit?".to_string());
let res = blocking_dialog(&self.streams.mg, builder);
if res == Some("yes".to_string()) {
gtk::main_quit();
}
},
ShowInfo => self.streams.mg.emit(Info("Info".to_string())),
ShowInput => input(&self.streams.mg, &self.model.relm, "Say something".to_string(),
"Oh yeah?".to_string(), Echo),
ShowQuestion => question(&self.streams.mg, &self.model.relm, "Do you want to quit?".to_string(),
char_slice!['y', 'n'], CheckQuit),
ShowWarning => self.streams.mg.emit(Warning("Warning".to_string())),
ToggleStatusBar => self.model.statusbar_visible = !self.model.statusbar_visible,
}
}
view! {
#[name="mg"]
Mg<AppCommand, AppSettings>(MODES, Ok("examples/main.conf".into()), Some("/home/bouanto".into()), vec![]) {
DarkTheme: true,
StatusBarVisible: self.model.statusbar_visible,
Title: self.model.title.clone(),
Variables: vec![("url", Box::new(|| "http://duckduckgo.com/lite".to_string()))],
gtk::Box {
orientation: Vertical,
gtk::Label {
text: &self.model.text,
},
#[name="entry"]
gtk::Entry {
},
gtk::Button {
label: "Alert",
clicked => ShowAlert,
},
gtk::Button {
label: "Info",
clicked => ShowInfo,
},
gtk::Button {
label: "Warning",
clicked => ShowWarning,
},
gtk::Button {
label: "Question",
clicked => ShowQuestion,
focus_on_click: false,
},
gtk::Button {
label: "Input",
clicked => ShowInput,
},
gtk::Button {
label: "Blocking Input",
clicked => ShowBlockingInput,
},
gtk::Button {
label: "Toggle status bar",
clicked => ToggleStatusBar,
},
},
StatusBarItem {
Color: Some(RGBA::red()),
text: "Rightmost",
},
StatusBarItem {
text: "Test",
},
AppClose => Command(Quit),
CustomCommand(Insert) => mg@SetMode("insert"),
CustomCommand(Normal) => mg@SetMode("normal"),
CustomCommand(ref command) => Command(command.clone()),
ModeChanged(ref mode) => NewMode(mode.clone()),
SettingChanged(ref setting) => Setting(setting.clone()),
}
}
}
fn main() {
pretty_env_logger::init();
Win::run(()).unwrap();
}
#[derive(Clone, Debug, Setting)]
pub enum CustomSetting {
#[default]
Choice,
OtherChoice,
}
#[derive(Commands)]
pub enum AppCommand {
#[special_command(identifier="?")]
BackwardSearch(String),
#[completion(hidden)]
DeleteEntry,
#[completion(hidden)]
Follow,
Insert,
Normal,
#[help(text="Open the url")]
Open(String),
#[help(text="Quit the application")]
Quit,
#[special_command(incremental, identifier="/")]
Search(String),
#[count]
ShowCount(Option<u32>),
#[help(text="Open the url in a new window")]
WinOpen(String),
}
#[derive(Default, Settings)]
pub struct AppSettings {
boolean: bool,
custom_set: CustomSetting,
#[help(text="The window title")]
title_len: i64,
width: i64,
window_title: String,
}