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
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License in the LICENSE-APACHE file or at:
// https://www.apache.org/licenses/LICENSE-2.0
//! Widget data types
use super::Id;
#[allow(unused)] use super::Widget;
use crate::geom::Rect;
#[cfg(feature = "winit")] pub use winit::window::Icon;
/// An icon used for the window titlebar, taskbar, etc.
#[cfg(not(feature = "winit"))]
#[derive(Clone)]
pub struct Icon;
#[cfg(not(feature = "winit"))]
impl Icon {
/// Creates an `Icon` from 32bpp RGBA data.
///
/// The length of `rgba` must be divisible by 4, and `width * height` must equal
/// `rgba.len() / 4`. Otherwise, this will return a `BadIcon` error.
pub fn from_rgba(
rgba: Vec<u8>,
width: u32,
height: u32,
) -> Result<Self, impl std::error::Error> {
let _ = (rgba, width, height);
Result::<Self, std::convert::Infallible>::Ok(Icon)
}
}
/// Common widget data
///
/// This type may be used for a [`Widget`]'s `core: widget_core!()` field.
#[derive(Default, Debug)]
pub struct CoreData {
pub rect: Rect,
pub id: Id,
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
#[cfg(debug_assertions)]
pub status: WidgetStatus,
}
/// Note: the clone has default-initialised identifier.
/// Configuration and layout solving is required as for any other widget.
impl Clone for CoreData {
fn clone(&self) -> Self {
CoreData {
rect: self.rect,
..CoreData::default()
}
}
}
/// Widget state tracker
///
/// This struct is used to track status of widget operations and panic in case
/// of inappropriate call order (such cases are memory safe but may cause
/// incorrect widget behaviour).
///
/// It is not used in release builds.
#[cfg_attr(not(feature = "internal_doc"), doc(hidden))]
#[cfg_attr(doc_cfg, doc(cfg(internal_doc)))]
#[cfg(debug_assertions)]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub enum WidgetStatus {
#[default]
New,
Configured,
SizeRulesX,
SizeRulesY,
SetRect,
}
#[cfg(debug_assertions)]
impl WidgetStatus {
fn require(&self, id: &Id, expected: Self) {
if *self < expected {
panic!("WidgetStatus of {id}: require {expected:?}, found {self:?}");
}
}
/// Configure
pub fn configure(&mut self, _id: &Id) {
// re-configure does not require repeating other actions
*self = (*self).max(WidgetStatus::Configured);
}
/// Update
pub fn update(&self, id: &Id) {
self.require(id, WidgetStatus::Configured);
// Update-after-configure is already guaranteed (see impls module).
// NOTE: Update-after-data-change should be required but is hard to
// detect; we could store a data hash but draw does not receive data.
// As such we don't bother recording this operation.
}
/// Size rules
pub fn size_rules(&mut self, id: &Id, axis: crate::layout::AxisInfo) {
// NOTE: Possibly this is too strict and we should not require
// re-running size_rules(vert) or set_rect afterwards?
if axis.is_horizontal() {
self.require(id, WidgetStatus::Configured);
*self = WidgetStatus::SizeRulesX;
} else {
self.require(id, WidgetStatus::SizeRulesX);
*self = WidgetStatus::SizeRulesY;
}
}
/// Set rect
pub fn set_rect(&mut self, id: &Id) {
self.require(id, WidgetStatus::SizeRulesY);
*self = WidgetStatus::SetRect;
}
pub fn require_rect(&self, id: &Id) {
self.require(id, WidgetStatus::SetRect);
}
}