add popover menu

This commit is contained in:
sleptworld 2024-01-26 00:41:54 +08:00
parent 0af39648c0
commit 8a855557da
4 changed files with 82 additions and 66 deletions

View File

@ -1,12 +1,17 @@
use super::{control_panel::ControlPanelModel, render_panel::RenderPanelModel};
use gtk::prelude::GtkApplicationExt;
use gtk::{
prelude::{ApplicationExt, ButtonExt, DialogExt, GtkWindowExt, ToggleButtonExt, WidgetExt},
prelude::{
ApplicationExt, BoxExt, ButtonExt, DialogExt, GtkWindowExt, ToggleButtonExt, WidgetExt,
},
traits::OrientableExt,
};
use relm4::actions::{AccelsPlus, ActionablePlus, RelmAction, RelmActionGroup};
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)]
pub enum AppMode {
@ -27,9 +32,6 @@ pub struct AppModel {
control: Controller<ControlPanelModel>,
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)]
impl SimpleComponent for AppModel {
@ -38,26 +40,46 @@ impl SimpleComponent for AppModel {
type Output = ();
view! {
#[root]
main_window=adw::ApplicationWindow {
set_default_width: 1200,
set_default_height: 900,
set_focus_on_click:true,
// set_titlebar: Some(&gtk::HeaderBar::new()),
gtk::Box{
set_orientation: gtk::Orientation::Vertical,
set_valign:gtk::Align::Fill,
set_spacing:2,
adw::HeaderBar {
#[wrap(Some)]
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.render.widget(),
},
connect_close_request[sender] => move |_| {
sender.input(AppMsg::CloseRequest);
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(())
.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();
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 {
mode: AppMode::View,
@ -118,6 +120,10 @@ impl SimpleComponent for AppModel {
};
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 }
}

View File

@ -160,7 +160,7 @@ impl Component for MonitorModel {
_ => 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 {
render_range: (4.0, 53.3, 73.3, 135.0),

View File

@ -36,16 +36,11 @@ pub struct RenderStatus {
pub(super) motion: RenderMotion,
pub(super) scale: f32,
pub(super) translate: Option<(f32, f32)>,
pub(super) view_range: Option<((f64, f64), (f64, f64))>,
translation: Option<(f64, f64)>,
init_translation: (f64, f64),
}
struct Fonts {
sans: FontId,
bold: FontId,
light: FontId,
}
pub struct Render {
pub(super) exterior: RefCell<ExteriorWidget>,
pub(super) interior: RefCell<InteriorWidget>,
@ -72,12 +67,11 @@ impl Default for Render {
#[glib::object_subclass]
impl ObjectSubclass for Render {
const NAME: &'static str = "MyRender";
const NAME: &'static str = "Render";
type Type = super::Render;
type ParentType = gtk::GLArea;
}
// Trait shared by all GObjects
impl ObjectImpl for Render {
fn constructed(&self) {
self.parent_constructed();
@ -86,13 +80,11 @@ impl ObjectImpl for Render {
}
}
// Trait shared by all widgets
impl WidgetImpl for Render {}
impl GLAreaImpl for Render {
fn resize(&self, width: i32, height: i32) {
self.status.borrow_mut().window_size = Some((width, height));
println!("resize: {}, {}", width, height);
self.ensure_canvas();
let mut canvas = self.canvas.borrow_mut();
let canvas = canvas.as_mut().unwrap();
@ -119,11 +111,9 @@ impl GLAreaImpl for Render {
}
fn render(&self, context: &gtk::gdk::GLContext) -> bool {
println!("render");
self.ensure_canvas();
let configs = self.config.borrow();
{
let (w, h) = {
let mut canvas = self.canvas.borrow_mut();
let canvas = canvas.as_mut().unwrap();
@ -138,9 +128,26 @@ impl GLAreaImpl for Render {
(h as i32 * dpi) as u32,
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();
match status.motion {
RenderMotion::Translate => {
@ -228,7 +235,7 @@ impl Render {
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 (w, h) = self.window_size().unwrap();
let (w, h) = (
@ -295,13 +302,16 @@ impl Render {
}
pub(super) fn set_view(&self, range: (f64, f64, f64, f64)) {
println!("set_view");
let (lat1, lat2, lon1, lon2) = range;
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));
}
self.status
.borrow_mut()
.view_range
.replace(((lat1, lat2), (lon1, lon2)));
// 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));
// }
}
}

View File

@ -184,7 +184,7 @@ impl Render {
}
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 {