mkgraphic 0.4.2

A Rust port of the cycfi/elements GUI framework
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
//! Element module - the core of the UI framework.
//!
//! Elements are the fundamental building blocks of the UI. This module provides:
//!
//! - [`Element`]: The base trait for all UI elements
//! - [`proxy`]: Proxy elements that wrap other elements
//! - [`composite`]: Container elements that hold multiple children
//! - [`tile`]: Layout elements (vtile, htile)
//! - [`align`]: Alignment elements
//! - [`margin`]: Margin elements
//! - [`size`]: Size constraint elements
//! - [`layer`]: Layered elements
//! - [`slider`]: Slider elements for value selection
//! - [`checkbox`]: Checkbox and radio button elements
//! - [`switch`]: Toggle switch elements
//! - [`dial`]: Rotary dial/knob elements
//! - [`text_box`]: Text input elements
//! - [`menu`]: Menu and popup elements
//! - [`list`]: List and dropdown elements
//! - [`grid`]: Grid layout element
//! - [`floating`]: Floating/draggable elements
//! - [`status_bar`]: Status bar element
//! - [`thumbwheel`]: Thumbwheel element
//! - [`scroll`]: Scrollable container element
//! - [`tabs`]: Tab bar element
//! - [`tooltip`]: Tooltip element
//! - [`progress`]: Progress bar element

pub mod align;
pub mod button;
pub mod chat_history;
pub mod checkbox;
pub mod code_editor;
pub mod composite;
pub mod context;
pub mod design_canvas;
pub mod dial;
pub mod floating;
pub mod grid;
pub mod label;
pub mod layer;
pub mod list;
pub mod margin;
pub mod markdown_view;
pub mod menu;
pub mod progress;
pub mod proxy;
pub mod scroll;
pub mod size;
pub mod slider;
pub mod splitter;
pub mod status_bar;
pub mod switch;
pub mod tabs;
pub mod text_box;
pub mod thumbwheel;
pub mod tile;
pub mod tooltip;
pub mod tree;

use std::any::Any;
use std::sync::{Arc, Weak};

use crate::support::point::{Axis, Point};
use crate::view::{CursorTracking, DropInfo, KeyInfo, MouseButton, TextInfo};

/// The maximum extent value (effectively infinite).
pub const FULL_EXTENT: f32 = 1e30;

/// View limits define the minimum and maximum sizes of an element.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ViewLimits {
    pub min: Point,
    pub max: Point,
}

impl ViewLimits {
    /// Creates new view limits.
    pub const fn new(min: Point, max: Point) -> Self {
        Self { min, max }
    }

    /// Creates view limits with zero minimum and full extent maximum.
    pub const fn full() -> Self {
        Self {
            min: Point::new(0.0, 0.0),
            max: Point::new(FULL_EXTENT, FULL_EXTENT),
        }
    }

    /// Creates fixed-size view limits.
    pub const fn fixed(width: f32, height: f32) -> Self {
        Self {
            min: Point::new(width, height),
            max: Point::new(width, height),
        }
    }

    /// Creates view limits with a minimum size.
    pub const fn min_size(width: f32, height: f32) -> Self {
        Self {
            min: Point::new(width, height),
            max: Point::new(FULL_EXTENT, FULL_EXTENT),
        }
    }

    /// Returns the minimum value for the given axis.
    pub fn min_for(&self, axis: Axis) -> f32 {
        self.min[axis]
    }

    /// Returns the maximum value for the given axis.
    pub fn max_for(&self, axis: Axis) -> f32 {
        self.max[axis]
    }
}

impl Default for ViewLimits {
    fn default() -> Self {
        Self::full()
    }
}

/// View stretch defines how an element stretches to fill available space.
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct ViewStretch {
    pub x: f32,
    pub y: f32,
}

impl ViewStretch {
    /// Creates a new view stretch.
    pub const fn new(x: f32, y: f32) -> Self {
        Self { x, y }
    }

    /// Creates a uniform view stretch.
    pub const fn uniform(value: f32) -> Self {
        Self { x: value, y: value }
    }

    /// Returns the stretch value for the given axis.
    pub fn for_axis(&self, axis: Axis) -> f32 {
        match axis {
            Axis::X => self.x,
            Axis::Y => self.y,
        }
    }
}

impl Default for ViewStretch {
    fn default() -> Self {
        Self { x: 1.0, y: 1.0 }
    }
}

/// Focus request type.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FocusRequest {
    /// Make the topmost element the focus.
    FromTop,
    /// Make the bottommost element the focus.
    FromBottom,
    /// Restore the previous focus state.
    RestorePrevious,
}

/// Tracking state for mouse interactions.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Tracking {
    /// No tracking is happening.
    None,
    /// Tracking has just started.
    Begin,
    /// Tracking is ongoing.
    While,
    /// Tracking has just ended.
    End,
}

/// The base trait for all UI elements.
///
/// Elements are lightweight objects that handle rendering, event processing,
/// and layout calculations. They form a hierarchical tree structure where
/// composite elements can contain child elements.
pub trait Element: Send + Sync + Any {
    // --- Display ---

    /// Returns the size limits of this element.
    fn limits(&self, ctx: &BasicContext) -> ViewLimits {
        ViewLimits::full()
    }

    /// Returns the stretch factor of this element.
    fn stretch(&self) -> ViewStretch {
        ViewStretch::default()
    }

    /// Returns the span (for grid layouts).
    fn span(&self) -> u32 {
        1
    }

    /// Performs hit testing to find the element at the given point.
    ///
    /// Returns `Some` if this element is hit, `None` otherwise.
    /// The default implementation returns `None` - concrete types should override this
    /// to return `Some(self)` when hit.
    fn hit_test(&self, ctx: &Context, p: Point, leaf: bool, control: bool) -> Option<&dyn Element> {
        None
    }

    /// Returns true if the element contains the given point (within current bounds).
    fn contains(&self, ctx: &Context, p: Point) -> bool {
        ctx.bounds.contains(p)
    }

    /// Draws this element.
    fn draw(&self, ctx: &Context) {}

    /// Draws transient overlay content (e.g. an expanded dropdown/popup) that
    /// must appear above every sibling, regardless of tree order. Containers
    /// call this in a second pass after all children have drawn their normal
    /// content, so overlays are never occluded by later siblings. Wrapper
    /// elements should forward this to their subject; the default is a no-op.
    fn draw_overlay(&self, _ctx: &Context) {}

    /// Performs layout calculations.
    fn layout(&mut self, ctx: &Context) {}

    /// Refreshes the element, triggering a redraw.
    fn refresh(&self, ctx: &Context, outward: i32) {}

    // --- Control ---

    /// Returns true if this element wants to receive control events.
    fn wants_control(&self) -> bool {
        false
    }

    /// Handles mouse click events.
    ///
    /// Returns true if the event was handled.
    fn click(&mut self, ctx: &Context, btn: MouseButton) -> bool {
        false
    }

    /// Handles mouse click events (immutable version for use with Arc).
    ///
    /// Returns true if the event was handled.
    /// Default implementation returns false - override this for elements
    /// that need to handle clicks through Arc<dyn Element>.
    fn handle_click(&self, _ctx: &Context, _btn: MouseButton) -> bool {
        false
    }

    /// Handles mouse drag events.
    fn drag(&mut self, ctx: &Context, btn: MouseButton) {}

    /// Handles mouse drag events (immutable version for use with Arc).
    fn handle_drag(&self, _ctx: &Context, _btn: MouseButton) {}

    /// Handles keyboard events.
    ///
    /// Returns true if the event was handled.
    fn key(&mut self, ctx: &Context, k: KeyInfo) -> bool {
        false
    }

    /// Handles keyboard events (immutable version for use with Arc).
    fn handle_key(&self, _ctx: &Context, _k: KeyInfo) -> bool {
        false
    }

    /// Handles text input events.
    ///
    /// Returns true if the event was handled.
    fn text(&mut self, ctx: &Context, info: TextInfo) -> bool {
        false
    }

    /// Handles text input events (immutable version for use with Arc).
    fn handle_text(&self, _ctx: &Context, _info: TextInfo) -> bool {
        false
    }

    /// Handles cursor (mouse move) events.
    ///
    /// Returns true if the event was handled.
    fn cursor(&mut self, ctx: &Context, p: Point, status: CursorTracking) -> bool {
        false
    }

    /// Handles scroll events.
    ///
    /// Returns true if the event was handled.
    fn scroll(&mut self, ctx: &Context, dir: Point, p: Point) -> bool {
        false
    }

    /// Handles scroll events (immutable version for use with Arc).
    fn handle_scroll(&self, _ctx: &Context, _dir: Point, _p: Point) -> bool {
        false
    }

    /// Enables or disables the element.
    fn enable(&mut self, state: bool) {}

    /// Returns true if the element is enabled.
    fn is_enabled(&self) -> bool {
        true
    }

    // --- Focus ---

    /// Returns true if this element wants to receive focus.
    fn wants_focus(&self) -> bool {
        false
    }

    /// Called when the element begins receiving focus.
    fn begin_focus(&mut self, req: FocusRequest) {}

    /// Called when the element loses focus.
    ///
    /// Returns true if focus was successfully released.
    fn end_focus(&mut self) -> bool {
        true
    }

    /// Returns the currently focused child element, if any.
    fn focus(&self) -> Option<&dyn Element> {
        None
    }

    /// Returns a mutable reference to the currently focused child element, if any.
    fn focus_mut(&mut self) -> Option<&mut dyn Element> {
        None
    }

    /// Clears focus from this element and all children (immutable version).
    /// This is used when clicking elsewhere to unfocus text inputs, etc.
    fn clear_focus(&self) {}

    // --- Drag and Drop ---

    /// Handles drag tracking events.
    fn track_drop(&mut self, ctx: &Context, info: &DropInfo, status: CursorTracking) {}

    /// Handles drop events.
    ///
    /// Returns true if the drop was accepted.
    fn drop(&mut self, ctx: &Context, info: &DropInfo) -> bool {
        false
    }

    // --- Type info ---

    /// Returns the class name of this element (for debugging).
    fn class_name(&self) -> &'static str {
        std::any::type_name::<Self>()
    }

    /// Returns this element as Any for downcasting.
    fn as_any(&self) -> &dyn Any;

    /// Returns this element as mutable Any for downcasting.
    fn as_any_mut(&mut self) -> &mut dyn Any;
}

/// A shared pointer to an element.
pub type ElementPtr = Arc<dyn Element>;

/// A weak pointer to an element.
pub type WeakElementPtr = Weak<dyn Element>;

/// Creates a shared element pointer.
pub fn share<E: Element + 'static>(element: E) -> ElementPtr {
    Arc::new(element)
}

/// An empty element that does nothing.
#[derive(Debug, Clone, Copy, Default)]
pub struct Empty;

impl Element for Empty {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut dyn Any {
        self
    }
}

/// Creates an empty element.
pub fn empty() -> Empty {
    Empty
}

// Re-exports
pub use composite::{Composite, CompositeBase, Storage};
pub use context::{BasicContext, Context};
pub use proxy::{Proxy, ProxyBase};