Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

page indicator for fixed layouts #1153

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/rnote-engine/src/document/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ impl Document {
}

#[allow(unused)]
pub(crate) fn calc_n_pages(&self) -> u32 {
pub fn calc_n_pages(&self) -> u32 {
// Avoid div by 0
if self.format.height() > 0.0 && self.format.width() > 0.0 {
(self.width / self.format.width()).ceil() as u32
Expand Down
11 changes: 11 additions & 0 deletions crates/rnote-engine/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,6 +680,17 @@ impl Engine {
self.camera_set_offset_expand(new_offset)
}

/// go to the page number for fixed layouts
pub fn go_to_page(&mut self, page_number: f64) -> WidgetFlags {
let zoom = self.camera.zoom();
let previous_offset = self.camera.offset();
let new_offset = na::vector![
previous_offset.x,
(page_number - 1.0) * self.document.format.height() * zoom
];
self.camera_set_offset_expand(new_offset)
}

/// Resize the doc when in autoexpanding layouts. called e.g. when finishing a new stroke.
///
/// Background rendering then needs to be updated.
Expand Down
6 changes: 6 additions & 0 deletions crates/rnote-ui/data/ui/mainheader.ui
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@
<child type="end">
<object class="GtkBox" id="right_buttons_box">
<property name="spacing">3</property>
<child>
<object class="GtkSpinButton" id="page_spin">
<property name="orientation">horizontal</property>
<property name="numeric">true</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="tooltip-text" translatable="yes">Save Document</property>
Expand Down
37 changes: 35 additions & 2 deletions crates/rnote-ui/src/appwindow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use adw::{prelude::*, subclass::prelude::*};
use gettextrs::gettext;
use gtk4::{gdk, gio, glib, Application, IconTheme};
use rnote_compose::Color;
use rnote_engine::document::Layout;
use rnote_engine::ext::GdkRGBAExt;
use rnote_engine::pens::pensconfig::brushconfig::BrushStyle;
use rnote_engine::pens::pensconfig::shaperconfig::ShaperStyle;
Expand Down Expand Up @@ -200,13 +201,12 @@ impl RnAppWindow {

// Returns true if the flags indicate that any loop that handles the flags should be quit. (usually an async event loop)
pub(crate) fn handle_widget_flags(&self, widget_flags: WidgetFlags, canvas: &RnCanvas) {
//tracing::debug!("handling widget flags: '{widget_flags:?}'");

if widget_flags.redraw {
canvas.queue_draw();
}
if widget_flags.resize {
canvas.queue_resize();
self.refresh_pages(canvas);
}
if widget_flags.refresh_ui {
self.refresh_ui_from_engine(&self.active_tab_wrapper());
Expand Down Expand Up @@ -492,6 +492,38 @@ impl RnAppWindow {
self.main_header().main_title().set_subtitle(&subtitle);
}

pub(crate) fn refresh_pages(&self, canvas: &RnCanvas) {
let layout = canvas.engine_ref().document.layout;
match layout {
Layout::FixedSize | Layout::ContinuousVertical => {
self.main_header().page_spin().set_visible(true);
let n_pages = canvas.engine_ref().document.calc_n_pages();
self.main_header()
.page_spin()
.set_range(1.0, n_pages as f64);

// zoom need to be taken into account

// slight offset : for now, because going to the page will
// give the previous page when the go_to_page function is called
// hence a cascade of calls are made until the first page is shown
// maybe we should set the page number based on the page visible
// at the center of the viewport instead
let page_number = ((canvas.engine_ref().camera.offset().y + 0.01)
/ (canvas.engine_ref().document.format.height()
* canvas.engine_ref().camera.zoom()))
.ceil()
.max(1.0);
self.main_header().page_spin().set_value(page_number);
Comment on lines +511 to +517
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should probably only trigger the set_value if the page number is actually different from the actual value

  • use block_signal/unblock_signal on the page_spin so that the function to change the page isn't called twice (thanks @Clemapfel for the idea)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like doing this is harder than it seems because glib::signal::SignalHandlerId does not implement Clone, hence it's difficult to save the value and use it in another function to block/unblock things

}
_ => {
// for now, not really working for infinite modes
self.main_header().page_spin().set_visible(false)
}
}
canvas.set_refresh_pages(false); // reset this property after dealing with the update
}

/// Open the file, with import dialogs when appropriate.
///
/// When the file is a rnote save file, `rnote_file_new_tab` determines if a new tab is opened,
Expand Down Expand Up @@ -873,6 +905,7 @@ impl RnAppWindow {
.refresh_ui(active_tab);
self.sidebar().settings_panel().refresh_ui(active_tab);
self.refresh_titles(active_tab);
self.refresh_pages(&active_tab.canvas());
}

/// Sync the state from the previous active tab and the current one. Used when the selected tab changes.
Expand Down
5 changes: 5 additions & 0 deletions crates/rnote-ui/src/canvas/canvaslayout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ mod imp {
.engine_mut()
.update_content_rendering_current_viewport();
}

if old_viewport != new_viewport {
// update the page number
canvas.set_refresh_pages(true);
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/rnote-ui/src/canvas/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ pub(crate) fn handle_pointer_controller_event(
match pen_state {
PenState::Up => {
canvas.enable_drawing_cursor(false);
// refresh the page number

let (ep, wf) = canvas.engine_mut().handle_pen_event(
PenEvent::Up {
Expand Down
41 changes: 41 additions & 0 deletions crates/rnote-ui/src/canvas/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ struct Connections {
appwindow_scalefactor: Option<glib::SignalHandlerId>,
appwindow_save_in_progress: Option<glib::SignalHandlerId>,
appwindow_unsaved_changes: Option<glib::SignalHandlerId>,
appwindow_refresh_pages: Option<glib::SignalHandlerId>,
appwindow_touch_drawing: Option<glib::Binding>,
appwindow_show_drawing_cursor: Option<glib::Binding>,
appwindow_regular_cursor: Option<glib::Binding>,
Expand Down Expand Up @@ -78,6 +79,7 @@ mod imp {
pub(crate) output_file_expect_write: Cell<bool>,
pub(crate) save_in_progress: Cell<bool>,
pub(crate) unsaved_changes: Cell<bool>,
pub(crate) refresh_pages: Cell<bool>,
pub(crate) empty: Cell<bool>,
pub(crate) touch_drawing: Cell<bool>,
pub(crate) show_drawing_cursor: Cell<bool>,
Expand Down Expand Up @@ -172,6 +174,7 @@ mod imp {
output_file_expect_write: Cell::new(false),
save_in_progress: Cell::new(false),
unsaved_changes: Cell::new(false),
refresh_pages: Cell::new(false),
empty: Cell::new(true),
touch_drawing: Cell::new(false),
show_drawing_cursor: Cell::new(false),
Expand Down Expand Up @@ -260,6 +263,9 @@ mod imp {
glib::ParamSpecBoolean::builder("unsaved-changes")
.default_value(false)
.build(),
glib::ParamSpecBoolean::builder("refresh-pages")
.default_value(false)
.build(),
glib::ParamSpecBoolean::builder("empty")
.default_value(true)
.build(),
Expand Down Expand Up @@ -290,6 +296,7 @@ mod imp {
"output-file" => self.output_file.borrow().to_value(),
"save-in-progress" => self.save_in_progress.get().to_value(),
"unsaved-changes" => self.unsaved_changes.get().to_value(),
"refresh-pages" => self.refresh_pages.get().to_value(),
"empty" => self.empty.get().to_value(),
"hadjustment" => self.hadjustment.borrow().to_value(),
"vadjustment" => self.vadjustment.borrow().to_value(),
Expand Down Expand Up @@ -323,6 +330,11 @@ mod imp {
value.get().expect("The value needs to be of type `bool`");
self.unsaved_changes.replace(unsaved_changes);
}
"refresh-pages" => {
let refresh_pages: bool =
value.get().expect("The value needs to be of type `bool`");
self.refresh_pages.replace(refresh_pages);
}
"empty" => {
let empty: bool = value.get().expect("The value needs to be of type `bool`");
self.empty.replace(empty);
Expand Down Expand Up @@ -665,6 +677,18 @@ impl RnCanvas {
}
}

#[allow(unused)]
pub(crate) fn refresh_pages(&self) -> bool {
self.property::<bool>("refresh-pages")
}

#[allow(unused)]
pub(crate) fn set_refresh_pages(&self, refresh_pages: bool) {
if self.imp().refresh_pages.get() != refresh_pages {
self.set_property("refresh-pages", refresh_pages.to_value());
}
}

#[allow(unused)]
pub(crate) fn empty(&self) -> bool {
self.property::<bool>("empty")
Expand Down Expand Up @@ -1078,6 +1102,7 @@ impl RnCanvas {
}

appwindow.refresh_titles(&appwindow.active_tab_wrapper());
appwindow.refresh_pages(&canvas);
}),
);

Expand Down Expand Up @@ -1114,6 +1139,13 @@ impl RnCanvas {
}),
);

let appwindow_refresh_pages = self.connect_notify_local(
Some("refresh-pages"),
clone!(@weak appwindow => move |_,_| {
appwindow.refresh_pages(&appwindow.active_tab_wrapper().canvas());
}),
);

// one per-appwindow property for touch-drawing
let appwindow_touch_drawing = appwindow
.bind_property("touch-drawing", self, "touch-drawing")
Expand Down Expand Up @@ -1224,6 +1256,12 @@ impl RnCanvas {
{
self.disconnect(old);
}
if let Some(old) = connections
.appwindow_refresh_pages
.replace(appwindow_refresh_pages)
{
self.disconnect(old)
}
if let Some(old) = connections
.appwindow_touch_drawing
.replace(appwindow_touch_drawing)
Expand Down Expand Up @@ -1281,6 +1319,9 @@ impl RnCanvas {
if let Some(old) = connections.appwindow_unsaved_changes.take() {
self.disconnect(old);
}
if let Some(old) = connections.appwindow_refresh_pages.take() {
self.disconnect(old);
}
if let Some(old) = connections.appwindow_touch_drawing.take() {
old.unbind();
}
Expand Down
1 change: 0 additions & 1 deletion crates/rnote-ui/src/canvaswrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,6 @@ mod imp {
widget_flags |= canvas.engine_mut().camera_set_offset_expand(new_camera_offset);
canvas.emit_handle_widget_flags(widget_flags);
}

glib::Propagation::Stop
}));
}
Expand Down
22 changes: 20 additions & 2 deletions crates/rnote-ui/src/mainheader.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Imports
use crate::{appmenu::RnAppMenu, appwindow::RnAppWindow, canvasmenu::RnCanvasMenu};
use gtk4::{
glib, prelude::*, subclass::prelude::*, Box, CompositeTemplate, EventControllerLegacy, Label,
ToggleButton, Widget,
glib, glib::clone, prelude::*, subclass::prelude::*, Box, CompositeTemplate,
EventControllerLegacy, Label, SpinButton, ToggleButton, Widget,
};

mod imp {
Expand All @@ -29,6 +29,8 @@ mod imp {
pub(crate) quickactions_box: TemplateChild<Box>,
#[template_child]
pub(crate) right_buttons_box: TemplateChild<Box>,
#[template_child]
pub(crate) page_spin: TemplateChild<SpinButton>,
}

#[glib::object_subclass]
Expand Down Expand Up @@ -105,6 +107,10 @@ impl RnMainHeader {
self.imp().appmenu.get()
}

pub(crate) fn page_spin(&self) -> SpinButton {
self.imp().page_spin.get()
}

pub(crate) fn init(&self, appwindow: &RnAppWindow) {
let imp = self.imp();

Expand All @@ -128,5 +134,17 @@ impl RnMainHeader {

capture_right.connect_event(|_, _| glib::Propagation::Stop);
imp.right_buttons_box.add_controller(capture_right);

imp.page_spin.set_increments(1.0, 1.0);
imp.page_spin
.connect_value_changed(clone!(@weak appwindow => move |spinb| {
let page_number = spinb.value();
let canvas = appwindow.active_tab_wrapper().canvas();
if !canvas.property::<bool>("refresh-pages") {
// go to the page indicated
let widget_flags = canvas.engine_mut().go_to_page(page_number);
appwindow.handle_widget_flags(widget_flags, &canvas);
}
}));
}
}
1 change: 1 addition & 0 deletions crates/rnote-ui/src/settingspanel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,7 @@ impl RnSettingsPanel {
.canvasmenu()
.fixedsize_quickactions_box()
.set_sensitive(document_layout == Layout::FixedSize);
appwindow.refresh_pages(&canvas);

if canvas.engine_ref().document.layout != document_layout {
let mut widget_flags = canvas.engine_mut().set_doc_layout(document_layout);
Expand Down