breadman: capture every stack page + the editor and new-note windows
--view (and now --screenshot) already opened any named stack page directly, so the other 9 pages (upcoming/todo/reminder/idea/note/ question/archive/settings/errors) needed zero new code — just registry entries in bread-capture. Two more real windows needed actual wiring: the per-note editor popover (editor::build_editor_popover, normally only reachable via a specific note card's edit button — screenshot mode calls the builder directly against the first real note in the store instead, since there's no button handle to synthesize a click on) and the "New Note" modal (show_add_note_window, same on_build-hook pattern already used for breadbar's wifi add-network dialog). The editor popover's first attempt parented it to the whole window, which put it at GTK4 Popover's default Top position — entirely above the window, clipped off the canvas in every capture despite mapping successfully (no error, just invisible). Anchoring to a real button (new_note_btn) with an explicit Bottom position fixed it.
This commit is contained in:
parent
55f5b6c3ae
commit
77b402833f
2 changed files with 96 additions and 9 deletions
|
|
@ -6,13 +6,25 @@
|
|||
//! hand-rolled `mod args` instead of bolting on a second parser that would
|
||||
//! reject its real flags (`--view`, `done`, `upcoming --plain`).
|
||||
//!
|
||||
//! `--screenshot <view>` doubles as the view selector — it's passed through
|
||||
//! as `initial_view` (the same field `--view` already sets) rather than
|
||||
//! `--screenshot <view>` doubles as the view selector for every named stack
|
||||
//! page ("all", "upcoming", "todo", ...) — it's passed through as
|
||||
//! `initial_view` (the same field `--view` already sets) rather than
|
||||
//! needing a separate mechanism, since breadman already supports opening
|
||||
//! directly to a named stack page.
|
||||
//!
|
||||
//! One view isn't a stack page at all: "editor" opens the per-note editor
|
||||
//! popover (`editor::build_editor_popover`), normally only reachable by
|
||||
//! clicking a real note card's edit button. Screenshot mode calls the same
|
||||
//! builder function directly against the first real note in the store
|
||||
//! (bypassing the button/click-handler entirely — there's no clean way to
|
||||
//! synthesize a click on a button that only ever existed as a local inside
|
||||
//! `build_note_card`, never stored anywhere else), with no-op save/delete/
|
||||
//! error callbacks since nothing here should actually persist a change.
|
||||
|
||||
use gtk4::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
/// Extra settle time after `map` for the first frame to actually paint
|
||||
|
|
@ -20,6 +32,11 @@ use std::time::Duration;
|
|||
/// anything has been drawn into it.
|
||||
const SETTLE_DELAY: Duration = Duration::from_millis(300);
|
||||
|
||||
/// Delay before popping the editor popover open — same reasoning as every
|
||||
/// other app's PRE_POPUP_DELAY: the parent window's own layout needs a beat
|
||||
/// to settle first.
|
||||
const PRE_POPUP_DELAY: Duration = Duration::from_millis(300);
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ScreenshotRequest {
|
||||
pub view: String,
|
||||
|
|
@ -33,12 +50,81 @@ pub struct ScreenshotRequest {
|
|||
/// it never returns control to the normal note-manager UI.
|
||||
///
|
||||
/// Unlike the other apps' `dispatch`, this doesn't validate `req.view`
|
||||
/// against a known-views list — an invalid name just falls through to
|
||||
/// breadman's own `unwrap_or("all")` default (see `build_app_window`),
|
||||
/// same as `--view` already behaves for a normal run.
|
||||
pub fn dispatch(window: >k4::ApplicationWindow, req: ScreenshotRequest) {
|
||||
/// against a known-views list for the stack-page case — an invalid name
|
||||
/// just falls through to breadman's own `unwrap_or("all")` default (see
|
||||
/// `build_app_window`), same as `--view` already behaves for a normal run.
|
||||
pub fn dispatch(
|
||||
window: >k4::ApplicationWindow,
|
||||
req: ScreenshotRequest,
|
||||
state: crate::AppState,
|
||||
editor_anchor: gtk4::Button,
|
||||
) {
|
||||
let output = req.output;
|
||||
let (width, height) = (req.width as i32, req.height as i32);
|
||||
|
||||
if req.view == "new-note" {
|
||||
window.connect_map(move |root| {
|
||||
let output = output.clone();
|
||||
let root = root.clone();
|
||||
let state = state.clone();
|
||||
gtk4::glib::timeout_add_local_once(PRE_POPUP_DELAY, move || {
|
||||
crate::show_add_note_window(&root, state, move |dialog| {
|
||||
let output = output.clone();
|
||||
dialog.connect_map(move |_| {
|
||||
let output = output.clone();
|
||||
gtk4::glib::timeout_add_local_once(SETTLE_DELAY, move || {
|
||||
finish(bread_screenshots::capture_region(0, 0, width, height, &output));
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if req.view == "editor" {
|
||||
window.connect_map(move |_| {
|
||||
let output = output.clone();
|
||||
let state = state.clone();
|
||||
let editor_anchor = editor_anchor.clone();
|
||||
gtk4::glib::timeout_add_local_once(PRE_POPUP_DELAY, move || {
|
||||
let Some(note) = state.notes.borrow().first().cloned() else {
|
||||
eprintln!("breadman: no notes in the store to build the editor view from");
|
||||
std::process::exit(1);
|
||||
};
|
||||
let morning = state.cfg.borrow().reminders.default_morning.clone();
|
||||
let store = Arc::new(state.write_store());
|
||||
let popover = crate::editor::build_editor_popover(
|
||||
¬e,
|
||||
store,
|
||||
morning,
|
||||
Rc::new(|_| {}),
|
||||
Rc::new(|| {}),
|
||||
Rc::new(|_| {}),
|
||||
);
|
||||
popover.set_parent(&editor_anchor);
|
||||
// Parenting to the whole window (rather than a small,
|
||||
// concretely-placed widget like the real edit-button call
|
||||
// site does) left the popover positioned above the window
|
||||
// entirely (GTK4's default Popover position is Top) — off
|
||||
// the top of the canvas and clipped out of every capture.
|
||||
// Anchoring to a real button plus an explicit Bottom
|
||||
// position keeps it inside the visible canvas.
|
||||
popover.set_position(gtk4::PositionType::Bottom);
|
||||
popover.set_autohide(false);
|
||||
let output = output.clone();
|
||||
popover.connect_map(move |_| {
|
||||
let output = output.clone();
|
||||
gtk4::glib::timeout_add_local_once(SETTLE_DELAY, move || {
|
||||
finish(bread_screenshots::capture_region(0, 0, width, height, &output));
|
||||
});
|
||||
});
|
||||
popover.popup();
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
window.connect_map(move |_| {
|
||||
let output = output.clone();
|
||||
gtk4::glib::timeout_add_local_once(SETTLE_DELAY, move || {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue