add popover menu
This commit is contained in:
parent
0af39648c0
commit
8a855557da
@ -1,12 +1,17 @@
|
|||||||
use super::{control_panel::ControlPanelModel, render_panel::RenderPanelModel};
|
use super::{control_panel::ControlPanelModel, render_panel::RenderPanelModel};
|
||||||
use gtk::prelude::GtkApplicationExt;
|
|
||||||
use gtk::{
|
use gtk::{
|
||||||
prelude::{ApplicationExt, ButtonExt, DialogExt, GtkWindowExt, ToggleButtonExt, WidgetExt},
|
prelude::{
|
||||||
|
ApplicationExt, BoxExt, ButtonExt, DialogExt, GtkWindowExt, ToggleButtonExt, WidgetExt,
|
||||||
|
},
|
||||||
traits::OrientableExt,
|
traits::OrientableExt,
|
||||||
};
|
};
|
||||||
|
use relm4::actions::{AccelsPlus, ActionablePlus, RelmAction, RelmActionGroup};
|
||||||
use relm4::*;
|
use relm4::*;
|
||||||
use adw::prelude::*;
|
use relm4::{gtk, ComponentParts, ComponentSender, RelmWidgetExt, SimpleComponent};
|
||||||
|
|
||||||
|
relm4::new_action_group!(WindowActionGroup, "win");
|
||||||
|
relm4::new_stateless_action!(ExampleAction, WindowActionGroup, "example");
|
||||||
|
relm4::new_stateful_action!(ExampleU8Action, WindowActionGroup, "example2", u8, u8);
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum AppMode {
|
pub enum AppMode {
|
||||||
@ -27,9 +32,6 @@ pub struct AppModel {
|
|||||||
control: Controller<ControlPanelModel>,
|
control: Controller<ControlPanelModel>,
|
||||||
render: Controller<RenderPanelModel>,
|
render: Controller<RenderPanelModel>,
|
||||||
}
|
}
|
||||||
relm4::new_action_group!(WindowActionGroup, "win");
|
|
||||||
relm4::new_stateless_action!(ExampleAction, WindowActionGroup, "example");
|
|
||||||
relm4::new_stateful_action!(ExampleU8Action, WindowActionGroup, "example2", u8, u8);
|
|
||||||
|
|
||||||
#[relm4::component(pub)]
|
#[relm4::component(pub)]
|
||||||
impl SimpleComponent for AppModel {
|
impl SimpleComponent for AppModel {
|
||||||
@ -38,26 +40,46 @@ impl SimpleComponent for AppModel {
|
|||||||
type Output = ();
|
type Output = ();
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
|
#[root]
|
||||||
main_window=adw::ApplicationWindow {
|
main_window=adw::ApplicationWindow {
|
||||||
set_default_width: 1200,
|
set_default_width: 1200,
|
||||||
set_default_height: 900,
|
set_default_height: 900,
|
||||||
set_focus_on_click:true,
|
set_focus_on_click:true,
|
||||||
// set_titlebar: Some(>k::HeaderBar::new()),
|
|
||||||
gtk::Box{
|
gtk::Box{
|
||||||
set_orientation: gtk::Orientation::Vertical,
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
set_valign:gtk::Align::Fill,
|
set_valign:gtk::Align::Fill,
|
||||||
|
set_spacing:2,
|
||||||
adw::HeaderBar {
|
adw::HeaderBar {
|
||||||
#[wrap(Some)]
|
#[wrap(Some)]
|
||||||
set_title_widget = &adw::WindowTitle {
|
set_title_widget = &adw::WindowTitle {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
gtk::Box{
|
||||||
|
set_margin_top: 2,
|
||||||
|
set_margin_horizontal: 10,
|
||||||
|
gtk::PopoverMenuBar::from_model(Some(&main_menu))->gtk::PopoverMenuBar{},
|
||||||
|
},
|
||||||
model.control.widget(),
|
model.control.widget(),
|
||||||
model.render.widget(),
|
model.render.widget(),
|
||||||
},
|
},
|
||||||
|
|
||||||
connect_close_request[sender] => move |_| {
|
connect_close_request[sender] => move |_| {
|
||||||
sender.input(AppMsg::CloseRequest);
|
sender.input(AppMsg::CloseRequest);
|
||||||
gtk::Inhibit(true)
|
gtk::Inhibit(true)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
popover_child = gtk::Spinner {
|
||||||
|
set_spinning: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
menu! {
|
||||||
|
main_menu: {
|
||||||
|
"File" {
|
||||||
|
"Example" => ExampleAction,
|
||||||
|
"Example2" => ExampleAction,
|
||||||
|
"Example toggle" => ExampleU8Action(1_u8),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,42 +96,22 @@ impl SimpleComponent for AppModel {
|
|||||||
.launch(())
|
.launch(())
|
||||||
.forward(sender.input_sender(), |a| AppMsg::Close);
|
.forward(sender.input_sender(), |a| AppMsg::Close);
|
||||||
|
|
||||||
relm4::menu! {
|
|
||||||
main_menu: {
|
|
||||||
custom: "my_widget",
|
|
||||||
"Example" => ExampleAction,
|
|
||||||
"Example2" => ExampleAction,
|
|
||||||
"Example toggle" => ExampleU8Action(1_u8),
|
|
||||||
section! {
|
|
||||||
"Section example" => ExampleAction,
|
|
||||||
"Example toggle" => ExampleU8Action(1_u8),
|
|
||||||
},
|
|
||||||
section! {
|
|
||||||
"Example" => ExampleAction,
|
|
||||||
"Example2" => ExampleAction,
|
|
||||||
"Example Value" => ExampleU8Action(1_u8),
|
|
||||||
},
|
|
||||||
"submenu1" {
|
|
||||||
"Example" => ExampleAction,
|
|
||||||
"Example2" => ExampleAction,
|
|
||||||
"Example toggle" => ExampleU8Action(1_u8),
|
|
||||||
"submenu2" {
|
|
||||||
"Example" => ExampleAction,
|
|
||||||
"Example2" => ExampleAction,
|
|
||||||
"Example toggle" => ExampleU8Action(1_u8),
|
|
||||||
"submenu3" {
|
|
||||||
"Example" => ExampleAction,
|
|
||||||
"Example2" => ExampleAction,
|
|
||||||
"Example toggle" => ExampleU8Action(1_u8),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let app = relm4::main_application();
|
let app = relm4::main_application();
|
||||||
relm4_icons::initialize_icons();
|
relm4_icons::initialize_icons();
|
||||||
app.set_menubar(Some(&main_menu));
|
|
||||||
|
app.set_accelerators_for_action::<ExampleAction>(&["<primary>W"]);
|
||||||
|
|
||||||
|
let action: RelmAction<ExampleAction> = {
|
||||||
|
RelmAction::new_stateless(move |_| {
|
||||||
|
println!("Statelesss action!");
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let action2: RelmAction<ExampleU8Action> =
|
||||||
|
RelmAction::new_stateful_with_target_value(&0, |_, state, _value| {
|
||||||
|
*state ^= 1;
|
||||||
|
dbg!(state);
|
||||||
|
});
|
||||||
|
|
||||||
let model = AppModel {
|
let model = AppModel {
|
||||||
mode: AppMode::View,
|
mode: AppMode::View,
|
||||||
@ -118,6 +120,10 @@ impl SimpleComponent for AppModel {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let widgets = view_output!();
|
let widgets = view_output!();
|
||||||
|
let mut group = RelmActionGroup::<WindowActionGroup>::new();
|
||||||
|
group.add_action(action);
|
||||||
|
group.add_action(action2);
|
||||||
|
group.register_for_widget(&widgets.main_window);
|
||||||
|
|
||||||
ComponentParts { model, widgets }
|
ComponentParts { model, widgets }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -160,7 +160,7 @@ impl Component for MonitorModel {
|
|||||||
_ => MonitorInputMsg::None,
|
_ => MonitorInputMsg::None,
|
||||||
});
|
});
|
||||||
|
|
||||||
let render_cfg = RenderConfig { padding: [20.0; 4] };
|
let render_cfg = RenderConfig { padding: [20.0,40.0,20.0,40.0] };
|
||||||
|
|
||||||
let model = MonitorModel {
|
let model = MonitorModel {
|
||||||
render_range: (4.0, 53.3, 73.3, 135.0),
|
render_range: (4.0, 53.3, 73.3, 135.0),
|
||||||
|
|||||||
@ -36,16 +36,11 @@ pub struct RenderStatus {
|
|||||||
pub(super) motion: RenderMotion,
|
pub(super) motion: RenderMotion,
|
||||||
pub(super) scale: f32,
|
pub(super) scale: f32,
|
||||||
pub(super) translate: Option<(f32, f32)>,
|
pub(super) translate: Option<(f32, f32)>,
|
||||||
|
pub(super) view_range: Option<((f64, f64), (f64, f64))>,
|
||||||
translation: Option<(f64, f64)>,
|
translation: Option<(f64, f64)>,
|
||||||
init_translation: (f64, f64),
|
init_translation: (f64, f64),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Fonts {
|
|
||||||
sans: FontId,
|
|
||||||
bold: FontId,
|
|
||||||
light: FontId,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Render {
|
pub struct Render {
|
||||||
pub(super) exterior: RefCell<ExteriorWidget>,
|
pub(super) exterior: RefCell<ExteriorWidget>,
|
||||||
pub(super) interior: RefCell<InteriorWidget>,
|
pub(super) interior: RefCell<InteriorWidget>,
|
||||||
@ -72,12 +67,11 @@ impl Default for Render {
|
|||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
impl ObjectSubclass for Render {
|
impl ObjectSubclass for Render {
|
||||||
const NAME: &'static str = "MyRender";
|
const NAME: &'static str = "Render";
|
||||||
type Type = super::Render;
|
type Type = super::Render;
|
||||||
type ParentType = gtk::GLArea;
|
type ParentType = gtk::GLArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trait shared by all GObjects
|
|
||||||
impl ObjectImpl for Render {
|
impl ObjectImpl for Render {
|
||||||
fn constructed(&self) {
|
fn constructed(&self) {
|
||||||
self.parent_constructed();
|
self.parent_constructed();
|
||||||
@ -86,13 +80,11 @@ impl ObjectImpl for Render {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Trait shared by all widgets
|
|
||||||
impl WidgetImpl for Render {}
|
impl WidgetImpl for Render {}
|
||||||
|
|
||||||
impl GLAreaImpl for Render {
|
impl GLAreaImpl for Render {
|
||||||
fn resize(&self, width: i32, height: i32) {
|
fn resize(&self, width: i32, height: i32) {
|
||||||
self.status.borrow_mut().window_size = Some((width, height));
|
self.status.borrow_mut().window_size = Some((width, height));
|
||||||
println!("resize: {}, {}", width, height);
|
|
||||||
self.ensure_canvas();
|
self.ensure_canvas();
|
||||||
let mut canvas = self.canvas.borrow_mut();
|
let mut canvas = self.canvas.borrow_mut();
|
||||||
let canvas = canvas.as_mut().unwrap();
|
let canvas = canvas.as_mut().unwrap();
|
||||||
@ -119,11 +111,9 @@ impl GLAreaImpl for Render {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render(&self, context: >k::gdk::GLContext) -> bool {
|
fn render(&self, context: >k::gdk::GLContext) -> bool {
|
||||||
|
|
||||||
println!("render");
|
|
||||||
self.ensure_canvas();
|
self.ensure_canvas();
|
||||||
let configs = self.config.borrow();
|
let configs = self.config.borrow();
|
||||||
{
|
let (w, h) = {
|
||||||
let mut canvas = self.canvas.borrow_mut();
|
let mut canvas = self.canvas.borrow_mut();
|
||||||
let canvas = canvas.as_mut().unwrap();
|
let canvas = canvas.as_mut().unwrap();
|
||||||
|
|
||||||
@ -138,9 +128,26 @@ impl GLAreaImpl for Render {
|
|||||||
(h as i32 * dpi) as u32,
|
(h as i32 * dpi) as u32,
|
||||||
Color::rgba(0, 0, 0, 255),
|
Color::rgba(0, 0, 0, 255),
|
||||||
);
|
);
|
||||||
}
|
(w, h)
|
||||||
|
};
|
||||||
|
|
||||||
{
|
let render_range = self.status.borrow().view_range.clone();
|
||||||
|
if let Some(((lat1, lat2), (lon1, lon2))) = render_range {
|
||||||
|
let mut status = self.status.borrow_mut();
|
||||||
|
|
||||||
|
let mapper = self.mapper.borrow();
|
||||||
|
|
||||||
|
let (tx, ty) = mapper.map((lon1, lat1)).unwrap();
|
||||||
|
status.translation.replace((tx, ty));
|
||||||
|
|
||||||
|
let (lon1, lat1) = mapper.map((lon1, lat1)).unwrap();
|
||||||
|
let (lon2, lat2) = mapper.map((lon2, lat2)).unwrap();
|
||||||
|
|
||||||
|
let scale = ((lat1 - lat2).abs() / h as f64).max((lon1 - lon2).abs() / w as f64);
|
||||||
|
status.scale_rate.replace(scale);
|
||||||
|
|
||||||
|
status.view_range = None;
|
||||||
|
} else {
|
||||||
let mut status = self.status.borrow_mut();
|
let mut status = self.status.borrow_mut();
|
||||||
match status.motion {
|
match status.motion {
|
||||||
RenderMotion::Translate => {
|
RenderMotion::Translate => {
|
||||||
@ -228,7 +235,7 @@ impl Render {
|
|||||||
self.status.borrow().window_size
|
self.status.borrow().window_size
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn window_range(&self) -> Option<((f64, f64), (f64, f64))> {
|
pub(super) fn view_range(&self) -> Option<((f64, f64), (f64, f64))> {
|
||||||
let padding = self.padding();
|
let padding = self.padding();
|
||||||
let (w, h) = self.window_size().unwrap();
|
let (w, h) = self.window_size().unwrap();
|
||||||
let (w, h) = (
|
let (w, h) = (
|
||||||
@ -295,13 +302,16 @@ impl Render {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn set_view(&self, range: (f64, f64, f64, f64)) {
|
pub(super) fn set_view(&self, range: (f64, f64, f64, f64)) {
|
||||||
println!("set_view");
|
|
||||||
let (lat1, lat2, lon1, lon2) = range;
|
let (lat1, lat2, lon1, lon2) = range;
|
||||||
if let Some((w, h)) = self.window_size() {
|
self.status
|
||||||
println!("w:{}, h:{}", w, h);
|
.borrow_mut()
|
||||||
let scale = ((lat1 - lat2).abs() / h as f64).max((lon1 - lon2).abs() / w as f64);
|
.view_range
|
||||||
self.status.borrow_mut().scale_rate.replace(scale);
|
.replace(((lat1, lat2), (lon1, lon2)));
|
||||||
self.set_translation((lat1, lon1));
|
// if let Some((w, h)) = self.window_size() {
|
||||||
}
|
// println!("w:{}, h:{}", w, h);
|
||||||
|
// let scale = ((lat1 - lat2).abs() / h as f64).max((lon1 - lon2).abs() / w as f64);
|
||||||
|
// self.status.borrow_mut().scale_rate.replace(scale);
|
||||||
|
// self.set_translation((lat1, lon1));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -184,7 +184,7 @@ impl Render {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_range(&self) -> ((f64, f64), (f64, f64)) {
|
pub fn render_range(&self) -> ((f64, f64), (f64, f64)) {
|
||||||
self.imp().window_range().unwrap()
|
self.imp().view_range().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_cms(&self) -> CMS {
|
pub fn create_cms(&self) -> CMS {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user