Skip to content

Commit

Permalink
feat: add overview for opened tabs (#1196)
Browse files Browse the repository at this point in the history
* feat: create an `AdwTabOverview` for opened tabs

Closes: #958

* improv: use normal `GtkButton` rather than `AdwTabButton`

* fix: close the window when closing the last tab

* improv: use `Ctrl+Shift+o` rather than `F12` for the overview

* refactor: switch to new glib::clone macro syntax

* Revert "fix: close the window when closing the last tab"

This reverts commit 728a795.

* chore: tweak view-grid button position

---------

Co-authored-by: Felix Zwettler <[email protected]>
  • Loading branch information
zefr0x and flxzt authored Nov 2, 2024
1 parent 16f4497 commit e767d39
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 30 deletions.
59 changes: 32 additions & 27 deletions crates/rnote-ui/data/ui/appwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,46 @@
</object>
</child>
<property name="content">
<object class="AdwOverlaySplitView" id="split_view">
<property name="pin-sidebar">true</property>
<property name="min-sidebar-width">500</property>
<property name="max-sidebar-width">550</property>
<property name="sidebar-width-fraction">0.3</property>
<!-- sidebar -->
<property name="sidebar">
<object class="RnSidebar" id="sidebar">
</object>
</property>
<!-- main view -->
<property name="content">
<object class="AdwToolbarView">
<property name="top-bar-style">raised</property>
<child type="top">
<object class="RnMainHeader" id="main_header">
<object class="AdwTabOverview" id="overview">
<property name="enable-new-tab">true</property>
<child>
<object class="AdwOverlaySplitView" id="split_view">
<property name="pin-sidebar">true</property>
<property name="min-sidebar-width">500</property>
<property name="max-sidebar-width">550</property>
<property name="sidebar-width-fraction">0.3</property>
<!-- sidebar -->
<property name="sidebar">
<object class="RnSidebar" id="sidebar">
</object>
</child>
</property>
<!-- main view -->
<property name="content">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="AdwTabBar" id="tabbar">
<object class="AdwToolbarView">
<property name="top-bar-style">raised</property>
<child type="top">
<object class="RnMainHeader" id="main_header">
</object>
</child>
<child>
<object class="RnOverlays" id="overlays">
<property name="hexpand">true</property>
<property name="vexpand">true</property>
<property name="content">
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="AdwTabBar" id="tabbar">
</object>
</child>
<child>
<object class="RnOverlays" id="overlays">
<property name="hexpand">true</property>
<property name="vexpand">true</property>
</object>
</child>
</object>
</child>
</property>
</object>
</property>
</object>
</property>
</child>
</object>
</property>
</template>
Expand Down
7 changes: 7 additions & 0 deletions crates/rnote-ui/data/ui/mainheader.ui
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@
<property name="tooltip-text" translatable="yes">New Tab</property>
</object>
</child>
<child>
<object class="GtkButton">
<property name="icon-name">view-grid-symbolic</property>
<property name="action-name">overview.open</property>
<property name="tooltip-text" translatable="yes">View Open Tabs</property>
</object>
</child>
<child>
<object class="GtkToggleButton">
<property name="icon-name">focus-mode-symbolic</property>
Expand Down
6 changes: 6 additions & 0 deletions crates/rnote-ui/data/ui/shortcuts.ui
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@
<property name="accelerator">&lt;ctrl&gt;q</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes">Toggle Tabs Overview</property>
<property name="accelerator">&lt;ctrl&gt;&lt;shift&gt;o</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="title" translatable="yes">Open the Canvas-Menu</property>
Expand Down
13 changes: 13 additions & 0 deletions crates/rnote-ui/src/appwindow/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ impl RnAppWindow {
self.add_action(&action_open_canvasmenu);
let action_open_appmenu = gio::SimpleAction::new("open-appmenu", None);
self.add_action(&action_open_appmenu);
let action_toggle_overview = gio::SimpleAction::new("toggle-overview", None);
self.add_action(&action_toggle_overview);
let action_devel_mode =
gio::SimpleAction::new_stateful("devel-mode", None, &false.to_variant());
self.add_action(&action_devel_mode);
Expand Down Expand Up @@ -247,6 +249,16 @@ impl RnAppWindow {
}
));

// Toggle Tabs Overview
action_toggle_overview.connect_activate(clone!(
#[weak(rename_to=appwindow)]
self,
move |_, _| {
let overview = appwindow.overview();
overview.set_open(!overview.is_open());
}
));

// Developer mode
action_devel_mode.connect_activate(clone!(
#[weak]
Expand Down Expand Up @@ -1101,6 +1113,7 @@ impl RnAppWindow {
app.set_accels_for_action("win.active-tab-close", &["<Ctrl>w"]);
app.set_accels_for_action("win.fullscreen", &["F11"]);
app.set_accels_for_action("win.keyboard-shortcuts", &["<Ctrl>question"]);
app.set_accels_for_action("win.toggle-overview", &["<Ctrl><Shift>o"]);
app.set_accels_for_action("win.open-canvasmenu", &["F9"]);
app.set_accels_for_action("win.open-appmenu", &["F10"]);
app.set_accels_for_action("win.open-doc", &["<Ctrl>o"]);
Expand Down
21 changes: 21 additions & 0 deletions crates/rnote-ui/src/appwindow/imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub(crate) struct RnAppWindow {
pub(crate) focus_mode: Cell<bool>,
pub(crate) close_in_progress: Cell<bool>,

#[template_child]
pub(crate) overview: TemplateChild<adw::TabOverview>,
#[template_child]
pub(crate) main_header: TemplateChild<RnMainHeader>,
#[template_child]
Expand Down Expand Up @@ -59,6 +61,7 @@ impl Default for RnAppWindow {
focus_mode: Cell::new(false),
close_in_progress: Cell::new(false),

overview: TemplateChild::<adw::TabOverview>::default(),
main_header: TemplateChild::<RnMainHeader>::default(),
split_view: TemplateChild::<adw::OverlaySplitView>::default(),
sidebar: TemplateChild::<RnSidebar>::default(),
Expand Down Expand Up @@ -105,6 +108,7 @@ impl ObjectImpl for RnAppWindow {
);

self.setup_input();
self.setup_overview();
self.setup_split_view();
self.setup_tabbar();
}
Expand Down Expand Up @@ -372,6 +376,23 @@ impl RnAppWindow {
.replace(Some(drawing_pad_controller));
}

fn setup_overview(&self) {
self.overview.set_view(Some(&self.overlays.tabview()));

let obj = self.obj();

// Create new tab via tab overview
self.overview.connect_create_tab(clone!(
#[weak(rename_to=appwindow)]
obj,
#[upgrade_or_panic]
move |_| {
let wrapper = appwindow.new_canvas_wrapper();
appwindow.append_wrapper_new_tab(&wrapper)
}
));
}

fn setup_tabbar(&self) {
self.tabbar.set_view(Some(&self.overlays.tabview()));
}
Expand Down
4 changes: 4 additions & 0 deletions crates/rnote-ui/src/appwindow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ impl RnAppWindow {
self.application().unwrap().downcast::<RnApp>().unwrap()
}

pub(crate) fn overview(&self) -> adw::TabOverview {
self.imp().overview.get()
}

pub(crate) fn main_header(&self) -> RnMainHeader {
self.imp().main_header.get()
}
Expand Down
40 changes: 37 additions & 3 deletions crates/rnote-ui/src/canvas/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ struct Connections {
vadjustment: Option<glib::SignalHandlerId>,
tab_page_output_file: Option<glib::Binding>,
tab_page_unsaved_changes: Option<glib::Binding>,
tab_page_invalidate_thumbnail: Option<glib::SignalHandlerId>,
appwindow_output_file: Option<glib::SignalHandlerId>,
appwindow_scalefactor: Option<glib::SignalHandlerId>,
appwindow_save_in_progress: Option<glib::SignalHandlerId>,
Expand Down Expand Up @@ -421,9 +422,12 @@ mod imp {

fn signals() -> &'static [glib::subclass::Signal] {
static SIGNALS: Lazy<Vec<glib::subclass::Signal>> = Lazy::new(|| {
vec![glib::subclass::Signal::builder("handle-widget-flags")
.param_types([WidgetFlagsBoxed::static_type()])
.build()]
vec![
glib::subclass::Signal::builder("handle-widget-flags")
.param_types([WidgetFlagsBoxed::static_type()])
.build(),
glib::subclass::Signal::builder("invalidate-thumbnail").build(),
]
});
SIGNALS.as_ref()
}
Expand Down Expand Up @@ -744,6 +748,10 @@ impl RnCanvas {
);
}

pub(super) fn emit_invalidate_thumbnail(&self) {
self.emit_by_name::<()>("invalidate-thumbnail", &[]);
}

pub(crate) fn last_export_dir(&self) -> Option<gio::File> {
self.imp().last_export_dir.borrow().clone()
}
Expand Down Expand Up @@ -949,6 +957,7 @@ impl RnCanvas {
appwindow.overlays().progressbar_abort();
} else {
appwindow.overlays().progressbar_finish();
canvas.emit_invalidate_thumbnail();
}
}
));
Expand Down Expand Up @@ -1401,6 +1410,9 @@ impl RnCanvas {
if let Some(old) = connections.tab_page_unsaved_changes.take() {
old.unbind();
}
if let Some(old) = connections.tab_page_invalidate_thumbnail.take() {
self.disconnect(old);
}
}

/// When the widget is the child of a tab page, we want to connect their titles, icons, ..
Expand Down Expand Up @@ -1430,6 +1442,22 @@ impl RnCanvas {
.sync_create()
.build();

// handle invalidating cached thumbnail in the tabs overview panel
let tab_page_invalidate_thumbnail = self.connect_local(
"invalidate-thumbnail",
false,
clone!(
#[weak]
page,
#[upgrade_or]
None,
move |_| {
page.invalidate_thumbnail();
None
}
),
);

let mut connections = self.imp().connections.borrow_mut();
if let Some(old) = connections
.tab_page_output_file
Expand All @@ -1443,6 +1471,12 @@ impl RnCanvas {
{
old.unbind();
}
if let Some(old) = connections
.tab_page_invalidate_thumbnail
.replace(tab_page_invalidate_thumbnail)
{
self.disconnect(old);
}
}

pub(crate) fn bounds(&self) -> Aabb {
Expand Down

0 comments on commit e767d39

Please sign in to comment.