noctua/src/domain/document/core/page.rs
wfx 6002b37406 feat: UI rewrite - TEA architecture, eliminate sync pattern
Complete UI layer refactoring to achieve Clean Architecture + TEA principles.

Major Changes:
- Eliminated sync.rs (76 LOC of manual synchronization)
- Restructured AppModel: pure UI state only
  - Introduced AppMode enum (View, Crop, Transform, Fullscreen)
  - Added Viewport struct (scale, pan, canvas, cached_image_handle)
  - Added PanelState struct (left, right panels)
- Removed all cached document data from UI layer
- Views now access DocumentManager directly (no caching)
- Update functions work on both model and manager directly

Architecture:
- TEA-compliant: Single source of truth, unidirectional flow
- Clean separation: UI state vs Document state
- No manual synchronization required

Benefits:
- Simplified codebase: -1,986 LOC net (-75.6%)
- Better maintainability: Clear responsibilities
- Type-safe state: Enums instead of flags
- Performance: Cached rendering where needed

Refactored Files:
- src/ui/model.rs: Complete rewrite
- src/ui/update.rs: Complete rewrite
- src/ui/views/*: Updated to use new architecture
- src/ui/views/meta_panel.rs: Extracted from panels.rs

Testing:
- All 24 unit tests passing
- Compiles successfully (cargo check, cargo build)
- 32 warnings (non-critical, future features)

BREAKING CHANGES: None (internal refactoring only)

Co-authored-by: Clean Architecture principles
Co-authored-by: TEA (The Elm Architecture) pattern
2026-02-05 10:41:51 +01:00

74 lines
1.8 KiB
Rust

// SPDX-License-Identifier: GPL-3.0-or-later
// src/domain/document/core/page.rs
//
// Page abstraction for multi-page documents.
use cosmic::widget::image::Handle as ImageHandle;
/// Represents a single page in a multi-page document.
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct Page {
/// Page index (0-based).
pub index: usize,
/// Page width in pixels.
pub width: u32,
/// Page height in pixels.
pub height: u32,
/// Optional thumbnail handle.
pub thumbnail: Option<ImageHandle>,
}
impl Page {
/// Create a new page.
#[must_use]
pub fn new(index: usize, width: u32, height: u32) -> Self {
Self {
index,
width,
height,
thumbnail: None,
}
}
/// Create a page with a thumbnail.
#[must_use]
pub fn with_thumbnail(index: usize, width: u32, height: u32, thumbnail: ImageHandle) -> Self {
Self {
index,
width,
height,
thumbnail: Some(thumbnail),
}
}
/// Set the thumbnail for this page.
pub fn set_thumbnail(&mut self, thumbnail: ImageHandle) {
self.thumbnail = Some(thumbnail);
}
/// Check if this page has a thumbnail.
#[must_use]
pub fn has_thumbnail(&self) -> bool {
self.thumbnail.is_some()
}
/// Get the aspect ratio of the page.
#[must_use]
pub fn aspect_ratio(&self) -> f32 {
if self.height == 0 {
1.0
} else {
#[allow(clippy::cast_precision_loss)]
{
self.width as f32 / self.height as f32
}
}
}
/// Get page dimensions as a tuple.
#[must_use]
pub fn dimensions(&self) -> (u32, u32) {
(self.width, self.height)
}
}