mirror of
https://github.com/danbulant/cushy
synced 2026-07-07 20:20:46 +00:00
Merged internal and public WindowHandle types
This commit is contained in:
parent
aa47539518
commit
76528ee374
5 changed files with 139 additions and 118 deletions
|
|
@ -15,7 +15,6 @@ use kludgine::shapes::{Shape, StrokeOptions};
|
||||||
use kludgine::{Color, Kludgine};
|
use kludgine::{Color, Kludgine};
|
||||||
|
|
||||||
use crate::animation::ZeroToOne;
|
use crate::animation::ZeroToOne;
|
||||||
use crate::context::sealed::WindowHandle;
|
|
||||||
use crate::graphics::Graphics;
|
use crate::graphics::Graphics;
|
||||||
use crate::styles::components::{
|
use crate::styles::components::{
|
||||||
CornerRadius, FontFamily, FontStyle, FontWeight, HighlightColor, LayoutOrder, LineHeight,
|
CornerRadius, FontFamily, FontStyle, FontWeight, HighlightColor, LayoutOrder, LineHeight,
|
||||||
|
|
@ -850,7 +849,6 @@ impl<'window> AsEventContext<'window> for GraphicsContext<'_, 'window, '_, '_, '
|
||||||
pub struct WidgetContext<'context, 'window> {
|
pub struct WidgetContext<'context, 'window> {
|
||||||
current_node: MountedWidget,
|
current_node: MountedWidget,
|
||||||
pub(crate) tree: Tree,
|
pub(crate) tree: Tree,
|
||||||
redraw_status: &'context InvalidationStatus,
|
|
||||||
window: &'context mut RunningWindow<'window>,
|
window: &'context mut RunningWindow<'window>,
|
||||||
theme: Cow<'context, ThemePair>,
|
theme: Cow<'context, ThemePair>,
|
||||||
cursor: &'context mut CursorState,
|
cursor: &'context mut CursorState,
|
||||||
|
|
@ -862,16 +860,12 @@ pub struct WidgetContext<'context, 'window> {
|
||||||
impl<'context, 'window> WidgetContext<'context, 'window> {
|
impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
current_node: MountedWidget,
|
current_node: MountedWidget,
|
||||||
redraw_status: &'context InvalidationStatus,
|
|
||||||
theme: &'context ThemePair,
|
theme: &'context ThemePair,
|
||||||
window: &'context mut RunningWindow<'window>,
|
window: &'context mut RunningWindow<'window>,
|
||||||
theme_mode: ThemeMode,
|
theme_mode: ThemeMode,
|
||||||
cursor: &'context mut CursorState,
|
cursor: &'context mut CursorState,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let enabled = current_node.enabled(&WindowHandle {
|
let enabled = current_node.enabled(&window.handle());
|
||||||
kludgine: window.handle(),
|
|
||||||
redraw_status: redraw_status.clone(),
|
|
||||||
});
|
|
||||||
let tree = current_node.tree();
|
let tree = current_node.tree();
|
||||||
Self {
|
Self {
|
||||||
pending_state: PendingState::Owned(PendingWidgetState {
|
pending_state: PendingState::Owned(PendingWidgetState {
|
||||||
|
|
@ -891,7 +885,6 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||||
},
|
},
|
||||||
cursor,
|
cursor,
|
||||||
current_node,
|
current_node,
|
||||||
redraw_status,
|
|
||||||
theme: Cow::Borrowed(theme),
|
theme: Cow::Borrowed(theme),
|
||||||
window,
|
window,
|
||||||
}
|
}
|
||||||
|
|
@ -902,7 +895,6 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||||
WidgetContext {
|
WidgetContext {
|
||||||
tree: self.tree.clone(),
|
tree: self.tree.clone(),
|
||||||
current_node: self.current_node.clone(),
|
current_node: self.current_node.clone(),
|
||||||
redraw_status: self.redraw_status,
|
|
||||||
window: &mut *self.window,
|
window: &mut *self.window,
|
||||||
theme: Cow::Borrowed(self.theme.as_ref()),
|
theme: Cow::Borrowed(self.theme.as_ref()),
|
||||||
pending_state: self.pending_state.borrowed(),
|
pending_state: self.pending_state.borrowed(),
|
||||||
|
|
@ -941,7 +933,6 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||||
},
|
},
|
||||||
current_node,
|
current_node,
|
||||||
tree: self.tree.clone(),
|
tree: self.tree.clone(),
|
||||||
redraw_status: self.redraw_status,
|
|
||||||
window: &mut *self.window,
|
window: &mut *self.window,
|
||||||
theme,
|
theme,
|
||||||
pending_state: self.pending_state.borrowed(),
|
pending_state: self.pending_state.borrowed(),
|
||||||
|
|
@ -1157,13 +1148,6 @@ impl<'context, 'window> WidgetContext<'context, 'window> {
|
||||||
self.effective_styles.try_get(query, self)
|
self.effective_styles.try_get(query, self)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn handle(&self) -> WindowHandle {
|
|
||||||
WindowHandle {
|
|
||||||
kludgine: self.window.handle(),
|
|
||||||
redraw_status: self.redraw_status.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the window containing this widget.
|
/// Returns the window containing this widget.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn window(&self) -> &RunningWindow<'window> {
|
pub fn window(&self) -> &RunningWindow<'window> {
|
||||||
|
|
@ -1297,6 +1281,19 @@ impl InvalidationStatus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Eq for InvalidationStatus {}
|
||||||
|
|
||||||
|
impl PartialEq for InvalidationStatus {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
Arc::ptr_eq(&self.invalidated, &other.invalidated)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::hash::Hash for InvalidationStatus {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
Arc::as_ptr(&self.invalidated).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A type chat can convert to a [`MountedWidget`] through a [`WidgetContext`].
|
/// A type chat can convert to a [`MountedWidget`] through a [`WidgetContext`].
|
||||||
pub trait ManageWidget {
|
pub trait ManageWidget {
|
||||||
/// The managed type, which can be `Option<MountedWidget>` or
|
/// The managed type, which can be `Option<MountedWidget>` or
|
||||||
|
|
@ -1392,52 +1389,11 @@ pub trait Trackable: sealed::Trackable {}
|
||||||
impl<T> Trackable for T where T: sealed::Trackable {}
|
impl<T> Trackable for T where T: sealed::Trackable {}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use std::hash::{Hash, Hasher};
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use crate::context::InvalidationStatus;
|
|
||||||
use crate::widget::WidgetId;
|
use crate::widget::WidgetId;
|
||||||
use crate::window::sealed::WindowCommand;
|
use crate::window::WindowHandle;
|
||||||
|
|
||||||
pub trait Trackable {
|
pub trait Trackable {
|
||||||
fn redraw_when_changed(&self, handle: WindowHandle);
|
fn redraw_when_changed(&self, handle: WindowHandle);
|
||||||
fn invalidate_when_changed(&self, handle: WindowHandle, id: WidgetId);
|
fn invalidate_when_changed(&self, handle: WindowHandle, id: WidgetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct WindowHandle {
|
|
||||||
pub(crate) kludgine: kludgine::app::WindowHandle<WindowCommand>,
|
|
||||||
pub(crate) redraw_status: InvalidationStatus,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for WindowHandle {}
|
|
||||||
|
|
||||||
impl PartialEq for WindowHandle {
|
|
||||||
fn eq(&self, other: &Self) -> bool {
|
|
||||||
Arc::ptr_eq(
|
|
||||||
&self.redraw_status.invalidated,
|
|
||||||
&other.redraw_status.invalidated,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Hash for WindowHandle {
|
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
|
||||||
Arc::as_ptr(&self.redraw_status.invalidated).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WindowHandle {
|
|
||||||
pub fn redraw(&self) {
|
|
||||||
if self.redraw_status.should_send_refresh() {
|
|
||||||
let _result = self.kludgine.send(WindowCommand::Redraw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn invalidate(&self, widget: WidgetId) {
|
|
||||||
if self.redraw_status.invalidate(widget) {
|
|
||||||
self.redraw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,11 @@ use alot::{LotId, Lots};
|
||||||
use kludgine::figures::units::{Px, UPx};
|
use kludgine::figures::units::{Px, UPx};
|
||||||
use kludgine::figures::{Point, Rect, Size};
|
use kludgine::figures::{Point, Rect, Size};
|
||||||
|
|
||||||
use crate::context::sealed::WindowHandle;
|
|
||||||
use crate::styles::{Styles, ThemePair, VisualOrder};
|
use crate::styles::{Styles, ThemePair, VisualOrder};
|
||||||
use crate::utils::IgnorePoison;
|
use crate::utils::IgnorePoison;
|
||||||
use crate::value::Value;
|
use crate::value::Value;
|
||||||
use crate::widget::{MountedWidget, WidgetId, WidgetInstance};
|
use crate::widget::{MountedWidget, WidgetId, WidgetInstance};
|
||||||
use crate::window::ThemeMode;
|
use crate::window::{ThemeMode, WindowHandle};
|
||||||
use crate::ConstraintLimit;
|
use crate::ConstraintLimit;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ use intentional::Assert;
|
||||||
use kempt::{Map, Sort};
|
use kempt::{Map, Sort};
|
||||||
|
|
||||||
use crate::animation::{AnimationHandle, DynamicTransition, IntoAnimate, LinearInterpolate, Spawn};
|
use crate::animation::{AnimationHandle, DynamicTransition, IntoAnimate, LinearInterpolate, Spawn};
|
||||||
use crate::context::sealed::WindowHandle;
|
|
||||||
use crate::context::{self, WidgetContext};
|
use crate::context::{self, WidgetContext};
|
||||||
use crate::utils::{run_in_bg, IgnorePoison, WithClone};
|
use crate::utils::{run_in_bg, IgnorePoison, WithClone};
|
||||||
use crate::widget::{Children, MakeWidget, MakeWidgetWithTag, WidgetId, WidgetInstance};
|
use crate::widget::{Children, MakeWidget, MakeWidgetWithTag, WidgetId, WidgetInstance};
|
||||||
use crate::widgets::{Radio, Select, Space, Switcher};
|
use crate::widgets::{Radio, Select, Space, Switcher};
|
||||||
|
use crate::window::WindowHandle;
|
||||||
|
|
||||||
/// An instance of a value that provides APIs to observe and react to its
|
/// An instance of a value that provides APIs to observe and react to its
|
||||||
/// contents.
|
/// contents.
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@ use kludgine::figures::{IntoSigned, IntoUnsigned, Point, Rect, Size};
|
||||||
use kludgine::Color;
|
use kludgine::Color;
|
||||||
|
|
||||||
use crate::app::{Application, Open, PendingApp, Run};
|
use crate::app::{Application, Open, PendingApp, Run};
|
||||||
use crate::context::sealed::WindowHandle;
|
|
||||||
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext, WidgetContext};
|
use crate::context::{AsEventContext, EventContext, GraphicsContext, LayoutContext, WidgetContext};
|
||||||
use crate::styles::components::{
|
use crate::styles::components::{
|
||||||
FontFamily, FontStyle, FontWeight, Heading1FontFamily, Heading1Style, Heading1Weight,
|
FontFamily, FontStyle, FontWeight, Heading1FontFamily, Heading1Style, Heading1Weight,
|
||||||
|
|
@ -43,7 +42,7 @@ use crate::widgets::{
|
||||||
Align, Button, Checkbox, Collapse, Container, Expand, Layers, Resize, Scroll, Space, Stack,
|
Align, Button, Checkbox, Collapse, Container, Expand, Layers, Resize, Scroll, Space, Stack,
|
||||||
Style, Themed, ThemedMode, Validated, Wrap,
|
Style, Themed, ThemedMode, Validated, Wrap,
|
||||||
};
|
};
|
||||||
use crate::window::{RunningWindow, ThemeMode, Window, WindowBehavior};
|
use crate::window::{RunningWindow, ThemeMode, Window, WindowBehavior, WindowHandle};
|
||||||
use crate::ConstraintLimit;
|
use crate::ConstraintLimit;
|
||||||
|
|
||||||
/// A type that makes up a graphical user interface.
|
/// A type that makes up a graphical user interface.
|
||||||
|
|
|
||||||
175
src/window.rs
175
src/window.rs
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
use std::hash::Hash;
|
||||||
use std::ops::{Deref, DerefMut, Not};
|
use std::ops::{Deref, DerefMut, Not};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::string::ToString;
|
use std::string::ToString;
|
||||||
|
|
@ -17,7 +18,7 @@ use kludgine::app::winit::event::{
|
||||||
use kludgine::app::winit::keyboard::{Key, NamedKey};
|
use kludgine::app::winit::keyboard::{Key, NamedKey};
|
||||||
use kludgine::app::winit::window;
|
use kludgine::app::winit::window;
|
||||||
use kludgine::app::WindowBehavior as _;
|
use kludgine::app::WindowBehavior as _;
|
||||||
use kludgine::cosmic_text::{Family, FamilyOwned};
|
use kludgine::cosmic_text::{fontdb, Family, FamilyOwned};
|
||||||
use kludgine::figures::units::{Px, UPx};
|
use kludgine::figures::units::{Px, UPx};
|
||||||
use kludgine::figures::{IntoSigned, IntoUnsigned, Point, Ranged, Rect, ScreenScale, Size, Zero};
|
use kludgine::figures::{IntoSigned, IntoUnsigned, Point, Ranged, Rect, ScreenScale, Size, Zero};
|
||||||
use kludgine::render::Drawing;
|
use kludgine::render::Drawing;
|
||||||
|
|
@ -46,6 +47,7 @@ use crate::{initialize_tracing, ConstraintLimit};
|
||||||
/// A currently running Gooey window.
|
/// A currently running Gooey window.
|
||||||
pub struct RunningWindow<'window> {
|
pub struct RunningWindow<'window> {
|
||||||
window: kludgine::app::Window<'window, WindowCommand>,
|
window: kludgine::app::Window<'window, WindowCommand>,
|
||||||
|
invalidation_status: InvalidationStatus,
|
||||||
gooey: Gooey,
|
gooey: Gooey,
|
||||||
focused: Dynamic<bool>,
|
focused: Dynamic<bool>,
|
||||||
occluded: Dynamic<bool>,
|
occluded: Dynamic<bool>,
|
||||||
|
|
@ -55,6 +57,7 @@ pub struct RunningWindow<'window> {
|
||||||
impl<'window> RunningWindow<'window> {
|
impl<'window> RunningWindow<'window> {
|
||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
window: kludgine::app::Window<'window, WindowCommand>,
|
window: kludgine::app::Window<'window, WindowCommand>,
|
||||||
|
invalidation_status: &InvalidationStatus,
|
||||||
gooey: &Gooey,
|
gooey: &Gooey,
|
||||||
focused: &Dynamic<bool>,
|
focused: &Dynamic<bool>,
|
||||||
occluded: &Dynamic<bool>,
|
occluded: &Dynamic<bool>,
|
||||||
|
|
@ -62,6 +65,7 @@ impl<'window> RunningWindow<'window> {
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
window,
|
window,
|
||||||
|
invalidation_status: invalidation_status.clone(),
|
||||||
gooey: gooey.clone(),
|
gooey: gooey.clone(),
|
||||||
focused: focused.clone(),
|
focused: focused.clone(),
|
||||||
occluded: occluded.clone(),
|
occluded: occluded.clone(),
|
||||||
|
|
@ -83,6 +87,20 @@ impl<'window> RunningWindow<'window> {
|
||||||
&self.occluded
|
&self.occluded
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Request that the window closes.
|
||||||
|
///
|
||||||
|
/// A window may disallow itself from being closed by customizing
|
||||||
|
/// [`WindowBehavior::close_requested`].
|
||||||
|
pub fn request_close(&self) {
|
||||||
|
self.handle().request_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a handle to this window.
|
||||||
|
#[must_use]
|
||||||
|
pub fn handle(&self) -> WindowHandle {
|
||||||
|
WindowHandle::new(self.window.handle(), self.invalidation_status.clone())
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns a dynamic that is synchronized with this window's inner size.
|
/// Returns a dynamic that is synchronized with this window's inner size.
|
||||||
///
|
///
|
||||||
/// Whenever the window is resized, this dynamic will be updated with the
|
/// Whenever the window is resized, this dynamic will be updated with the
|
||||||
|
|
@ -332,12 +350,14 @@ where
|
||||||
App: Application,
|
App: Application,
|
||||||
{
|
{
|
||||||
let gooey = app.gooey().clone();
|
let gooey = app.gooey().clone();
|
||||||
|
let redraw_status = InvalidationStatus::default();
|
||||||
let handle = GooeyWindow::<Behavior>::open_with(
|
let handle = GooeyWindow::<Behavior>::open_with(
|
||||||
app,
|
app,
|
||||||
sealed::Context {
|
sealed::Context {
|
||||||
user: self.context,
|
user: self.context,
|
||||||
settings: RefCell::new(sealed::WindowSettings {
|
settings: RefCell::new(sealed::WindowSettings {
|
||||||
gooey,
|
gooey,
|
||||||
|
redraw_status: redraw_status.clone(),
|
||||||
on_closed: self.on_closed,
|
on_closed: self.on_closed,
|
||||||
transparent: self.attributes.transparent,
|
transparent: self.attributes.transparent,
|
||||||
attributes: Some(self.attributes),
|
attributes: Some(self.attributes),
|
||||||
|
|
@ -356,7 +376,7 @@ where
|
||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(handle.map(WindowHandle::from))
|
Ok(handle.map(|handle| WindowHandle::new(handle, redraw_status)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_in(self, app: PendingApp) -> crate::Result {
|
fn run_in(self, app: PendingApp) -> crate::Result {
|
||||||
|
|
@ -455,7 +475,6 @@ where
|
||||||
EventContext::new(
|
EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
previously_active,
|
previously_active,
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
window,
|
window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -468,7 +487,6 @@ where
|
||||||
EventContext::new(
|
EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
default.clone(),
|
default.clone(),
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
window,
|
window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -487,7 +505,6 @@ where
|
||||||
EventContext::new(
|
EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
keyboard_activated,
|
keyboard_activated,
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
window,
|
window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -517,7 +534,6 @@ where
|
||||||
let mut context = EventContext::new(
|
let mut context = EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
managed,
|
managed,
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
window,
|
window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -591,37 +607,11 @@ where
|
||||||
|
|
||||||
root_mode.unwrap_or(RootMode::Fit)
|
root_mode.unwrap_or(RootMode::Fit)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
fn load_fonts(
|
||||||
enum RootMode {
|
settings: &mut sealed::WindowSettings,
|
||||||
Fit,
|
fontdb: &mut fontdb::Database,
|
||||||
Expand,
|
) -> FontState {
|
||||||
Align,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> kludgine::app::WindowBehavior<WindowCommand> for GooeyWindow<T>
|
|
||||||
where
|
|
||||||
T: WindowBehavior,
|
|
||||||
{
|
|
||||||
type Context = sealed::Context<T::Context>;
|
|
||||||
|
|
||||||
fn initialize(
|
|
||||||
window: kludgine::app::Window<'_, WindowCommand>,
|
|
||||||
graphics: &mut kludgine::Graphics<'_>,
|
|
||||||
context: Self::Context,
|
|
||||||
) -> Self {
|
|
||||||
let mut settings = context.settings.borrow_mut();
|
|
||||||
let gooey = settings.gooey.clone();
|
|
||||||
let occluded = settings.occluded.take().unwrap_or_default();
|
|
||||||
let focused = settings.focused.take().unwrap_or_default();
|
|
||||||
let theme = settings.theme.take().expect("theme always present");
|
|
||||||
let inner_size = settings.inner_size.take().unwrap_or_default();
|
|
||||||
let on_closed = settings.on_closed.take();
|
|
||||||
|
|
||||||
inner_size.set(window.inner_size());
|
|
||||||
|
|
||||||
let fontdb = graphics.font_system().db_mut();
|
|
||||||
for font_to_load in settings.font_data_to_load.drain(..) {
|
for font_to_load in settings.font_data_to_load.drain(..) {
|
||||||
fontdb.load_font_data(font_to_load);
|
fontdb.load_font_data(font_to_load);
|
||||||
}
|
}
|
||||||
|
|
@ -668,6 +658,39 @@ where
|
||||||
|| default_family(Family::Cursive),
|
|| default_family(Family::Cursive),
|
||||||
|name| fontdb.set_cursive_family(name),
|
|name| fontdb.set_cursive_family(name),
|
||||||
);
|
);
|
||||||
|
fonts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||||
|
enum RootMode {
|
||||||
|
Fit,
|
||||||
|
Expand,
|
||||||
|
Align,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> kludgine::app::WindowBehavior<WindowCommand> for GooeyWindow<T>
|
||||||
|
where
|
||||||
|
T: WindowBehavior,
|
||||||
|
{
|
||||||
|
type Context = sealed::Context<T::Context>;
|
||||||
|
|
||||||
|
fn initialize(
|
||||||
|
window: kludgine::app::Window<'_, WindowCommand>,
|
||||||
|
graphics: &mut kludgine::Graphics<'_>,
|
||||||
|
context: Self::Context,
|
||||||
|
) -> Self {
|
||||||
|
let mut settings = context.settings.borrow_mut();
|
||||||
|
let gooey = settings.gooey.clone();
|
||||||
|
let occluded = settings.occluded.take().unwrap_or_default();
|
||||||
|
let focused = settings.focused.take().unwrap_or_default();
|
||||||
|
let theme = settings.theme.take().expect("theme always present");
|
||||||
|
let inner_size = settings.inner_size.take().unwrap_or_default();
|
||||||
|
let on_closed = settings.on_closed.take();
|
||||||
|
|
||||||
|
inner_size.set(window.inner_size());
|
||||||
|
|
||||||
|
let fonts = Self::load_fonts(&mut settings, graphics.font_system().db_mut());
|
||||||
|
|
||||||
let theme_mode = match settings.theme_mode.take() {
|
let theme_mode = match settings.theme_mode.take() {
|
||||||
Some(Value::Dynamic(dynamic)) => {
|
Some(Value::Dynamic(dynamic)) => {
|
||||||
|
|
@ -678,8 +701,16 @@ where
|
||||||
None => Value::dynamic(window.theme().into()),
|
None => Value::dynamic(window.theme().into()),
|
||||||
};
|
};
|
||||||
let transparent = settings.transparent;
|
let transparent = settings.transparent;
|
||||||
|
let redraw_status = settings.redraw_status.clone();
|
||||||
let mut behavior = T::initialize(
|
let mut behavior = T::initialize(
|
||||||
&mut RunningWindow::new(window, &gooey, &focused, &occluded, &inner_size),
|
&mut RunningWindow::new(
|
||||||
|
window,
|
||||||
|
&redraw_status,
|
||||||
|
&gooey,
|
||||||
|
&focused,
|
||||||
|
&occluded,
|
||||||
|
&inner_size,
|
||||||
|
),
|
||||||
context.user,
|
context.user,
|
||||||
);
|
);
|
||||||
let tree = Tree::default();
|
let tree = Tree::default();
|
||||||
|
|
@ -701,7 +732,7 @@ where
|
||||||
widget: None,
|
widget: None,
|
||||||
},
|
},
|
||||||
mouse_buttons: AHashMap::default(),
|
mouse_buttons: AHashMap::default(),
|
||||||
redraw_status: InvalidationStatus::default(),
|
redraw_status,
|
||||||
initial_frame: true,
|
initial_frame: true,
|
||||||
occluded,
|
occluded,
|
||||||
focused,
|
focused,
|
||||||
|
|
@ -740,6 +771,7 @@ where
|
||||||
let resizable = window.winit().is_resizable();
|
let resizable = window.winit().is_resizable();
|
||||||
let mut window = RunningWindow::new(
|
let mut window = RunningWindow::new(
|
||||||
window,
|
window,
|
||||||
|
&self.redraw_status,
|
||||||
&self.gooey,
|
&self.gooey,
|
||||||
&self.focused,
|
&self.focused,
|
||||||
&self.occluded,
|
&self.occluded,
|
||||||
|
|
@ -752,7 +784,6 @@ where
|
||||||
let mut context = GraphicsContext {
|
let mut context = GraphicsContext {
|
||||||
widget: WidgetContext::new(
|
widget: WidgetContext::new(
|
||||||
self.root.clone(),
|
self.root.clone(),
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -876,6 +907,7 @@ where
|
||||||
&mut self.behavior,
|
&mut self.behavior,
|
||||||
&mut RunningWindow::new(
|
&mut RunningWindow::new(
|
||||||
window,
|
window,
|
||||||
|
&self.redraw_status,
|
||||||
&self.gooey,
|
&self.gooey,
|
||||||
&self.focused,
|
&self.focused,
|
||||||
&self.occluded,
|
&self.occluded,
|
||||||
|
|
@ -949,6 +981,7 @@ where
|
||||||
};
|
};
|
||||||
let mut window = RunningWindow::new(
|
let mut window = RunningWindow::new(
|
||||||
window,
|
window,
|
||||||
|
&self.redraw_status,
|
||||||
&self.gooey,
|
&self.gooey,
|
||||||
&self.focused,
|
&self.focused,
|
||||||
&self.occluded,
|
&self.occluded,
|
||||||
|
|
@ -957,7 +990,6 @@ where
|
||||||
let mut target = EventContext::new(
|
let mut target = EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
target,
|
target,
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -994,7 +1026,6 @@ where
|
||||||
let mut target = EventContext::new(
|
let mut target = EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
target,
|
target,
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -1055,6 +1086,7 @@ where
|
||||||
|
|
||||||
let mut window = RunningWindow::new(
|
let mut window = RunningWindow::new(
|
||||||
window,
|
window,
|
||||||
|
&self.redraw_status,
|
||||||
&self.gooey,
|
&self.gooey,
|
||||||
&self.focused,
|
&self.focused,
|
||||||
&self.occluded,
|
&self.occluded,
|
||||||
|
|
@ -1063,7 +1095,6 @@ where
|
||||||
let mut widget = EventContext::new(
|
let mut widget = EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
widget,
|
widget,
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -1091,6 +1122,7 @@ where
|
||||||
.unwrap_or_else(|| self.tree.widget(self.root.id()).expect("missing widget"));
|
.unwrap_or_else(|| self.tree.widget(self.root.id()).expect("missing widget"));
|
||||||
let mut window = RunningWindow::new(
|
let mut window = RunningWindow::new(
|
||||||
window,
|
window,
|
||||||
|
&self.redraw_status,
|
||||||
&self.gooey,
|
&self.gooey,
|
||||||
&self.focused,
|
&self.focused,
|
||||||
&self.occluded,
|
&self.occluded,
|
||||||
|
|
@ -1099,7 +1131,6 @@ where
|
||||||
let mut target = EventContext::new(
|
let mut target = EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
widget,
|
widget,
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -1124,6 +1155,7 @@ where
|
||||||
|
|
||||||
let mut window = RunningWindow::new(
|
let mut window = RunningWindow::new(
|
||||||
window,
|
window,
|
||||||
|
&self.redraw_status,
|
||||||
&self.gooey,
|
&self.gooey,
|
||||||
&self.focused,
|
&self.focused,
|
||||||
&self.occluded,
|
&self.occluded,
|
||||||
|
|
@ -1133,7 +1165,6 @@ where
|
||||||
EventContext::new(
|
EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
self.root.clone(),
|
self.root.clone(),
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -1152,7 +1183,6 @@ where
|
||||||
let mut context = EventContext::new(
|
let mut context = EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
handler.clone(),
|
handler.clone(),
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -1177,6 +1207,7 @@ where
|
||||||
if self.cursor.widget.take().is_some() {
|
if self.cursor.widget.take().is_some() {
|
||||||
let mut window = RunningWindow::new(
|
let mut window = RunningWindow::new(
|
||||||
window,
|
window,
|
||||||
|
&self.redraw_status,
|
||||||
&self.gooey,
|
&self.gooey,
|
||||||
&self.focused,
|
&self.focused,
|
||||||
&self.occluded,
|
&self.occluded,
|
||||||
|
|
@ -1185,7 +1216,6 @@ where
|
||||||
let mut context = EventContext::new(
|
let mut context = EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
self.root.clone(),
|
self.root.clone(),
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -1207,6 +1237,7 @@ where
|
||||||
) {
|
) {
|
||||||
let mut window = RunningWindow::new(
|
let mut window = RunningWindow::new(
|
||||||
window,
|
window,
|
||||||
|
&self.redraw_status,
|
||||||
&self.gooey,
|
&self.gooey,
|
||||||
&self.focused,
|
&self.focused,
|
||||||
&self.occluded,
|
&self.occluded,
|
||||||
|
|
@ -1217,7 +1248,6 @@ where
|
||||||
EventContext::new(
|
EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
self.root.clone(),
|
self.root.clone(),
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -1236,7 +1266,6 @@ where
|
||||||
&mut EventContext::new(
|
&mut EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
hovered.clone(),
|
hovered.clone(),
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -1276,7 +1305,6 @@ where
|
||||||
let mut context = EventContext::new(
|
let mut context = EventContext::new(
|
||||||
WidgetContext::new(
|
WidgetContext::new(
|
||||||
handler,
|
handler,
|
||||||
&self.redraw_status,
|
|
||||||
&self.current_theme,
|
&self.current_theme,
|
||||||
&mut window,
|
&mut window,
|
||||||
self.theme_mode.get(),
|
self.theme_mode.get(),
|
||||||
|
|
@ -1321,6 +1349,7 @@ where
|
||||||
WindowCommand::RequestClose => {
|
WindowCommand::RequestClose => {
|
||||||
let mut window = RunningWindow::new(
|
let mut window = RunningWindow::new(
|
||||||
window,
|
window,
|
||||||
|
&self.redraw_status,
|
||||||
&self.gooey,
|
&self.gooey,
|
||||||
&self.focused,
|
&self.focused,
|
||||||
&self.occluded,
|
&self.occluded,
|
||||||
|
|
@ -1367,6 +1396,7 @@ pub(crate) mod sealed {
|
||||||
use kludgine::figures::Size;
|
use kludgine::figures::Size;
|
||||||
|
|
||||||
use crate::app::Gooey;
|
use crate::app::Gooey;
|
||||||
|
use crate::context::InvalidationStatus;
|
||||||
use crate::styles::{FontFamilyList, ThemePair};
|
use crate::styles::{FontFamilyList, ThemePair};
|
||||||
use crate::value::{Dynamic, Value};
|
use crate::value::{Dynamic, Value};
|
||||||
use crate::widget::OnceCallback;
|
use crate::widget::OnceCallback;
|
||||||
|
|
@ -1379,6 +1409,7 @@ pub(crate) mod sealed {
|
||||||
|
|
||||||
pub struct WindowSettings {
|
pub struct WindowSettings {
|
||||||
pub gooey: Gooey,
|
pub gooey: Gooey,
|
||||||
|
pub redraw_status: InvalidationStatus,
|
||||||
pub attributes: Option<WindowAttributes>,
|
pub attributes: Option<WindowAttributes>,
|
||||||
pub occluded: Option<Dynamic<bool>>,
|
pub occluded: Option<Dynamic<bool>>,
|
||||||
pub focused: Option<Dynamic<bool>>,
|
pub focused: Option<Dynamic<bool>>,
|
||||||
|
|
@ -1501,20 +1532,56 @@ fn default_family(query: Family<'_>) -> Option<FamilyOwned> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A handle to an open Gooey window.
|
/// A handle to an open Gooey window.
|
||||||
pub struct WindowHandle(kludgine::app::WindowHandle<sealed::WindowCommand>);
|
#[derive(Clone)]
|
||||||
|
pub struct WindowHandle {
|
||||||
|
pub(crate) kludgine: kludgine::app::WindowHandle<WindowCommand>,
|
||||||
|
pub(crate) redraw_status: InvalidationStatus,
|
||||||
|
}
|
||||||
|
|
||||||
impl WindowHandle {
|
impl WindowHandle {
|
||||||
|
pub(crate) fn new(
|
||||||
|
kludgine: kludgine::app::WindowHandle<WindowCommand>,
|
||||||
|
redraw_status: InvalidationStatus,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
kludgine,
|
||||||
|
redraw_status,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Request that the window closes.
|
/// Request that the window closes.
|
||||||
///
|
///
|
||||||
/// A window may disallow itself from being closed by customizing
|
/// A window may disallow itself from being closed by customizing
|
||||||
/// [`WindowBehavior::close_requested`].
|
/// [`WindowBehavior::close_requested`].
|
||||||
pub fn request_close(&self) {
|
pub fn request_close(&self) {
|
||||||
let _result = self.0.send(sealed::WindowCommand::RequestClose);
|
let _result = self.kludgine.send(sealed::WindowCommand::RequestClose);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Requests that the window redraws.
|
||||||
|
pub fn redraw(&self) {
|
||||||
|
if self.redraw_status.should_send_refresh() {
|
||||||
|
let _result = self.kludgine.send(WindowCommand::Redraw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Marks `widget` as invalidated, and if needed, refreshes the window.
|
||||||
|
pub fn invalidate(&self, widget: WidgetId) {
|
||||||
|
if self.redraw_status.invalidate(widget) {
|
||||||
|
self.redraw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<kludgine::app::WindowHandle<sealed::WindowCommand>> for WindowHandle {
|
impl Eq for WindowHandle {}
|
||||||
fn from(handle: kludgine::app::WindowHandle<sealed::WindowCommand>) -> Self {
|
|
||||||
WindowHandle(handle)
|
impl PartialEq for WindowHandle {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.redraw_status == other.redraw_status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for WindowHandle {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.redraw_status.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue