mirror of
https://github.com/danbulant/cushy
synced 2026-06-19 22:41:10 +00:00
Added inner_size syncing
This adds upon the work in #94 by allowing the dynamic's value to be set and it cause the window size to change. I've ordered the resizing operations so that changes to the property are prioritized over automatic adjustments. This doesn't change the behavior for automatic adjustments in any way.
This commit is contained in:
parent
f9d0203ff5
commit
873e6d6f16
2 changed files with 136 additions and 65 deletions
|
|
@ -369,4 +369,17 @@ impl FontState {
|
|||
})
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn apply_font_family_list(
|
||||
&self,
|
||||
family: &FontFamilyList,
|
||||
fallback: impl FnOnce() -> Option<FamilyOwned>,
|
||||
apply: impl FnOnce(String),
|
||||
) {
|
||||
if let Some(FamilyOwned::Name(name)) =
|
||||
self.find_available_font_family(family).or_else(fallback)
|
||||
{
|
||||
apply(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
188
src/window.rs
188
src/window.rs
|
|
@ -36,7 +36,7 @@ use crate::graphics::{FontState, Graphics};
|
|||
use crate::styles::{Edges, FontFamilyList, ThemePair};
|
||||
use crate::tree::Tree;
|
||||
use crate::utils::ModifiersExt;
|
||||
use crate::value::{Dynamic, DynamicReader, IntoDynamic, IntoValue, Value};
|
||||
use crate::value::{Dynamic, DynamicReader, Generation, IntoDynamic, IntoValue, Value};
|
||||
use crate::widget::{
|
||||
EventHandling, MountedWidget, RootBehavior, Widget, WidgetId, WidgetInstance, HANDLED, IGNORED,
|
||||
};
|
||||
|
|
@ -79,12 +79,16 @@ impl<'window> RunningWindow<'window> {
|
|||
/// Returns a dynamic that is updated whenever this window's occlusion
|
||||
/// status changes.
|
||||
#[must_use]
|
||||
pub fn occluded(&self) -> &Dynamic<bool> {
|
||||
pub const fn occluded(&self) -> &Dynamic<bool> {
|
||||
&self.occluded
|
||||
}
|
||||
|
||||
/// Returns a dynamic that is updated whenever this window's inner size
|
||||
/// changes.
|
||||
/// Returns a dynamic that is synchronized with this window's inner size.
|
||||
///
|
||||
/// Whenever the window is resized, this dynamic will be updated with the
|
||||
/// new inner size. Setting a new value will request the new size from the
|
||||
/// operating system, but resize requests may be altered or ignored by the
|
||||
/// operating system.
|
||||
#[must_use]
|
||||
pub const fn inner_size(&self) -> &Dynamic<Size<UPx>> {
|
||||
&self.inner_size
|
||||
|
|
@ -205,11 +209,12 @@ impl Window<WidgetInstance> {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets `inner_size` to be the dynamic updated when this window's inner size
|
||||
/// is changed.
|
||||
/// Sets `inner_size` to be the dynamic syncrhonized with this window's
|
||||
/// inner size.
|
||||
///
|
||||
/// When the window is resized, the dynamic will contain its new size.
|
||||
/// `true`.
|
||||
/// When the window is resized, the dynamic will contain its new size. When
|
||||
/// the dynamic is updated with a new value, a resize request will be made
|
||||
/// with the new inner size.
|
||||
pub fn inner_size(mut self, inner_size: impl IntoDynamic<Size<UPx>>) -> Self {
|
||||
let inner_size = inner_size.into_dynamic();
|
||||
self.inner_size = Some(inner_size);
|
||||
|
|
@ -371,6 +376,7 @@ struct GooeyWindow<T> {
|
|||
occluded: Dynamic<bool>,
|
||||
focused: Dynamic<bool>,
|
||||
inner_size: Dynamic<Size<UPx>>,
|
||||
inner_size_generation: Generation,
|
||||
keyboard_activated: Option<WidgetId>,
|
||||
min_inner_size: Option<Size<UPx>>,
|
||||
max_inner_size: Option<Size<UPx>>,
|
||||
|
|
@ -573,8 +579,10 @@ where
|
|||
let gooey = settings.gooey.clone();
|
||||
let occluded = settings.occluded.take().unwrap_or_default();
|
||||
let focused = settings.focused.take().unwrap_or_default();
|
||||
let inner_size = settings.inner_size.take().unwrap_or_default();
|
||||
let theme = settings.theme.take().expect("theme always present");
|
||||
let inner_size = settings.inner_size.take().unwrap_or_default();
|
||||
|
||||
inner_size.set(window.inner_size());
|
||||
|
||||
let fontdb = graphics.font_system().db_mut();
|
||||
for font_to_load in settings.font_data_to_load.drain(..) {
|
||||
|
|
@ -582,55 +590,47 @@ where
|
|||
}
|
||||
|
||||
let fonts = FontState::new(fontdb);
|
||||
fonts.apply_font_family_list(
|
||||
&settings.serif_font_family,
|
||||
|| default_family(Family::Serif),
|
||||
|name| fontdb.set_serif_family(name),
|
||||
);
|
||||
|
||||
if let Some(FamilyOwned::Name(name)) = fonts
|
||||
.find_available_font_family(&settings.serif_font_family)
|
||||
.or_else(|| default_family(Family::Serif))
|
||||
{
|
||||
fontdb.set_serif_family(name);
|
||||
}
|
||||
|
||||
let bundled_font_name;
|
||||
#[cfg(feature = "roboto-flex")]
|
||||
{
|
||||
bundled_font_name = Some(String::from("Roboto Flex"));
|
||||
}
|
||||
#[cfg(not(feature = "roboto-flex"))]
|
||||
{
|
||||
bundled_font_name = None;
|
||||
}
|
||||
|
||||
if let Some(FamilyOwned::Name(name)) = fonts
|
||||
.find_available_font_family(&settings.sans_serif_font_family)
|
||||
.or_else(|| {
|
||||
if let Some(name) = bundled_font_name {
|
||||
Some(FamilyOwned::Name(name))
|
||||
} else {
|
||||
default_family(Family::SansSerif)
|
||||
fonts.apply_font_family_list(
|
||||
&settings.sans_serif_font_family,
|
||||
|| {
|
||||
let bundled_font_name;
|
||||
#[cfg(feature = "roboto-flex")]
|
||||
{
|
||||
bundled_font_name = Some(String::from("Roboto Flex"));
|
||||
}
|
||||
#[cfg(not(feature = "roboto-flex"))]
|
||||
{
|
||||
bundled_font_name = None;
|
||||
}
|
||||
})
|
||||
{
|
||||
fontdb.set_sans_serif_family(name);
|
||||
}
|
||||
|
||||
if let Some(FamilyOwned::Name(name)) = fonts
|
||||
.find_available_font_family(&settings.fantasy_font_family)
|
||||
.or_else(|| default_family(Family::Fantasy))
|
||||
{
|
||||
fontdb.set_fantasy_family(name);
|
||||
}
|
||||
if let Some(FamilyOwned::Name(name)) = fonts
|
||||
.find_available_font_family(&settings.monospace_font_family)
|
||||
.or_else(|| default_family(Family::Monospace))
|
||||
{
|
||||
fontdb.set_monospace_family(name);
|
||||
}
|
||||
if let Some(FamilyOwned::Name(name)) = fonts
|
||||
.find_available_font_family(&settings.cursive_font_family)
|
||||
.or_else(|| default_family(Family::Cursive))
|
||||
{
|
||||
fontdb.set_cursive_family(name);
|
||||
}
|
||||
bundled_font_name.map_or_else(
|
||||
|| default_family(Family::SansSerif),
|
||||
|name| Some(FamilyOwned::Name(name)),
|
||||
)
|
||||
},
|
||||
|name| fontdb.set_sans_serif_family(name),
|
||||
);
|
||||
fonts.apply_font_family_list(
|
||||
&settings.fantasy_font_family,
|
||||
|| default_family(Family::Fantasy),
|
||||
|name| fontdb.set_fantasy_family(name),
|
||||
);
|
||||
fonts.apply_font_family_list(
|
||||
&settings.monospace_font_family,
|
||||
|| default_family(Family::Monospace),
|
||||
|name| fontdb.set_monospace_family(name),
|
||||
);
|
||||
fonts.apply_font_family_list(
|
||||
&settings.cursive_font_family,
|
||||
|| default_family(Family::Cursive),
|
||||
|name| fontdb.set_cursive_family(name),
|
||||
);
|
||||
|
||||
let theme_mode = match settings.theme_mode.take() {
|
||||
Some(Value::Dynamic(dynamic)) => {
|
||||
|
|
@ -666,6 +666,7 @@ where
|
|||
initial_frame: true,
|
||||
occluded,
|
||||
focused,
|
||||
inner_size_generation: inner_size.generation(),
|
||||
inner_size,
|
||||
keyboard_activated: None,
|
||||
min_inner_size: None,
|
||||
|
|
@ -698,7 +699,13 @@ where
|
|||
.new_frame(self.redraw_status.invalidations().drain());
|
||||
|
||||
let resizable = window.winit().is_resizable();
|
||||
let mut window = RunningWindow::new(window, &self.gooey, &self.focused, &self.occluded, &self.inner_size);
|
||||
let mut window = RunningWindow::new(
|
||||
window,
|
||||
&self.gooey,
|
||||
&self.focused,
|
||||
&self.occluded,
|
||||
&self.inner_size,
|
||||
);
|
||||
let root_mode = self.constrain_window_resizing(resizable, &mut window, graphics);
|
||||
|
||||
self.fonts.next_frame();
|
||||
|
|
@ -741,7 +748,14 @@ where
|
|||
layout_size
|
||||
};
|
||||
let render_size = actual_size.min(window_size);
|
||||
if actual_size != window_size && !resizable {
|
||||
layout_context.redraw_when_changed(&self.inner_size);
|
||||
let inner_size_generation = self.inner_size.generation();
|
||||
if self.inner_size_generation != inner_size_generation {
|
||||
let _ = layout_context
|
||||
.winit()
|
||||
.request_inner_size(PhysicalSize::from(self.inner_size.get()));
|
||||
self.inner_size_generation = inner_size_generation;
|
||||
} else if actual_size != window_size && !resizable {
|
||||
let mut new_size = actual_size;
|
||||
if let Some(min_size) = self.min_inner_size {
|
||||
new_size = new_size.max(min_size);
|
||||
|
|
@ -825,7 +839,13 @@ where
|
|||
Self::request_close(
|
||||
&mut self.should_close,
|
||||
&mut self.behavior,
|
||||
&mut RunningWindow::new(window, &self.gooey, &self.focused, &self.occluded, &self.inner_size),
|
||||
&mut RunningWindow::new(
|
||||
window,
|
||||
&self.gooey,
|
||||
&self.focused,
|
||||
&self.occluded,
|
||||
&self.inner_size,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -865,6 +885,8 @@ where
|
|||
_kludgine: &mut Kludgine,
|
||||
) {
|
||||
self.inner_size.set(window.inner_size());
|
||||
// We want to prevent a resize request for this resized event.
|
||||
self.inner_size_generation = self.inner_size.generation();
|
||||
self.root.invalidate();
|
||||
}
|
||||
|
||||
|
|
@ -890,7 +912,13 @@ where
|
|||
let Some(target) = self.root.tree.widget_from_node(target) else {
|
||||
return;
|
||||
};
|
||||
let mut window = RunningWindow::new(window, &self.gooey, &self.focused, &self.occluded, &self.inner_size);
|
||||
let mut window = RunningWindow::new(
|
||||
window,
|
||||
&self.gooey,
|
||||
&self.focused,
|
||||
&self.occluded,
|
||||
&self.inner_size,
|
||||
);
|
||||
let mut target = EventContext::new(
|
||||
WidgetContext::new(
|
||||
target,
|
||||
|
|
@ -1000,7 +1028,13 @@ where
|
|||
.expect("missing widget")
|
||||
});
|
||||
|
||||
let mut window = RunningWindow::new(window, &self.gooey, &self.focused, &self.occluded, &self.inner_size);
|
||||
let mut window = RunningWindow::new(
|
||||
window,
|
||||
&self.gooey,
|
||||
&self.focused,
|
||||
&self.occluded,
|
||||
&self.inner_size,
|
||||
);
|
||||
let mut widget = EventContext::new(
|
||||
WidgetContext::new(
|
||||
widget,
|
||||
|
|
@ -1036,7 +1070,13 @@ where
|
|||
.widget(self.root.id())
|
||||
.expect("missing widget")
|
||||
});
|
||||
let mut window = RunningWindow::new(window, &self.gooey, &self.focused, &self.occluded, &self.inner_size);
|
||||
let mut window = RunningWindow::new(
|
||||
window,
|
||||
&self.gooey,
|
||||
&self.focused,
|
||||
&self.occluded,
|
||||
&self.inner_size,
|
||||
);
|
||||
let mut target = EventContext::new(
|
||||
WidgetContext::new(
|
||||
widget,
|
||||
|
|
@ -1063,7 +1103,13 @@ where
|
|||
let location = Point::<Px>::from(position);
|
||||
self.cursor.location = Some(location);
|
||||
|
||||
let mut window = RunningWindow::new(window, &self.gooey, &self.focused, &self.occluded, &self.inner_size);
|
||||
let mut window = RunningWindow::new(
|
||||
window,
|
||||
&self.gooey,
|
||||
&self.focused,
|
||||
&self.occluded,
|
||||
&self.inner_size,
|
||||
);
|
||||
|
||||
EventContext::new(
|
||||
WidgetContext::new(
|
||||
|
|
@ -1110,7 +1156,13 @@ where
|
|||
_device_id: DeviceId,
|
||||
) {
|
||||
if self.cursor.widget.take().is_some() {
|
||||
let mut window = RunningWindow::new(window, &self.gooey, &self.focused, &self.occluded, &self.inner_size);
|
||||
let mut window = RunningWindow::new(
|
||||
window,
|
||||
&self.gooey,
|
||||
&self.focused,
|
||||
&self.occluded,
|
||||
&self.inner_size,
|
||||
);
|
||||
let mut context = EventContext::new(
|
||||
WidgetContext::new(
|
||||
self.root.clone(),
|
||||
|
|
@ -1134,7 +1186,13 @@ where
|
|||
state: ElementState,
|
||||
button: MouseButton,
|
||||
) {
|
||||
let mut window = RunningWindow::new(window, &self.gooey, &self.focused, &self.occluded, &self.inner_size);
|
||||
let mut window = RunningWindow::new(
|
||||
window,
|
||||
&self.gooey,
|
||||
&self.focused,
|
||||
&self.occluded,
|
||||
&self.inner_size,
|
||||
);
|
||||
match state {
|
||||
ElementState::Pressed => {
|
||||
EventContext::new(
|
||||
|
|
@ -1266,8 +1324,8 @@ pub(crate) struct CursorState {
|
|||
pub(crate) mod sealed {
|
||||
use std::cell::RefCell;
|
||||
|
||||
use kludgine::figures::Size;
|
||||
use kludgine::figures::units::UPx;
|
||||
use kludgine::figures::Size;
|
||||
|
||||
use crate::styles::{FontFamilyList, ThemePair};
|
||||
use crate::value::{Dynamic, Value};
|
||||
|
|
|
|||
Loading…
Reference in a new issue