mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-01 14:21:16 +00:00
Native style: respond to the StyleChange event
So that color scheme is updated when switching to the dark style, for example Fixes #687
This commit is contained in:
parent
a5ea6dd087
commit
e4bd6bbfb8
8 changed files with 180 additions and 104 deletions
|
@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
|
|||
### Fixed
|
||||
|
||||
- Memory leak in C++
|
||||
- Properly change all the colors when switching dark mode on or of (#687)
|
||||
|
||||
## [0.1.5] - 2021-11-24
|
||||
|
||||
|
|
|
@ -382,10 +382,10 @@ fn gen_backend_qt(root_dir: &Path, include_dir: &Path) -> anyhow::Result<()> {
|
|||
|
||||
config.export.include = items.iter().map(|x| x.to_string()).collect();
|
||||
|
||||
config
|
||||
.export
|
||||
.body
|
||||
.insert("NativeStyleMetrics".to_owned(), " inline NativeStyleMetrics();".to_owned());
|
||||
config.export.body.insert(
|
||||
"NativeStyleMetrics".to_owned(),
|
||||
" inline NativeStyleMetrics(); inline ~NativeStyleMetrics();".to_owned(),
|
||||
);
|
||||
|
||||
let mut crate_dir = root_dir.to_owned();
|
||||
crate_dir.extend(["sixtyfps_runtime", "rendering_backends", "qt"].iter());
|
||||
|
|
|
@ -732,7 +732,12 @@ cbindgen_private::Flickable::~Flickable()
|
|||
|
||||
cbindgen_private::NativeStyleMetrics::NativeStyleMetrics()
|
||||
{
|
||||
sixtyfps_init_native_style_metrics(this);
|
||||
sixtyfps_native_style_metrics_init(this);
|
||||
}
|
||||
|
||||
cbindgen_private::NativeStyleMetrics::~NativeStyleMetrics()
|
||||
{
|
||||
sixtyfps_native_style_metrics_deinit(this);
|
||||
}
|
||||
#endif // !defined(DOXYGEN)
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ LICENSE END */
|
|||
|
||||
pub type FieldOffset<T, U> = const_field_offset::FieldOffset<T, U, const_field_offset::AllowPin>;
|
||||
use crate::items::PropertyAnimation;
|
||||
use alloc::rc::Rc;
|
||||
use core::convert::{TryFrom, TryInto};
|
||||
use core::pin::Pin;
|
||||
|
||||
|
@ -332,3 +333,8 @@ pub trait BuiltinItem: Sized {
|
|||
fn fields<Value: ValueType>() -> Vec<(&'static str, &'static dyn FieldInfo<Self, Value>)>;
|
||||
fn callbacks<Value: ValueType>() -> Vec<(&'static str, &'static dyn CallbackInfo<Self, Value>)>;
|
||||
}
|
||||
|
||||
/// Trait implemented by builtin globals
|
||||
pub trait BuiltinGlobal: BuiltinItem {
|
||||
fn new() -> Pin<Rc<Self>>;
|
||||
}
|
||||
|
|
|
@ -105,10 +105,10 @@ pub fn instantiate(description: &CompiledGlobal) -> (String, Pin<Rc<dyn GlobalCo
|
|||
}
|
||||
}
|
||||
impl Helper for () {}
|
||||
impl<T: rtti::BuiltinItem + Default + 'static, Next: Helper> Helper for (T, Next) {
|
||||
impl<T: rtti::BuiltinGlobal + 'static, Next: Helper> Helper for (T, Next) {
|
||||
fn instantiate(name: &str) -> Pin<Rc<dyn GlobalComponent>> {
|
||||
if name == T::name() {
|
||||
Rc::pin(T::default())
|
||||
T::new()
|
||||
} else {
|
||||
Next::instantiate(name)
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ fn main() {
|
|||
println!("cargo:rerun-if-changed=qt_widgets/scrollview.rs");
|
||||
println!("cargo:rerun-if-changed=qt_widgets/slider.rs");
|
||||
println!("cargo:rerun-if-changed=qt_widgets/spinbox.rs");
|
||||
println!("cargo:rerun-if-changed=qt_widgets/stylemetrics.rs");
|
||||
println!("cargo:rerun-if-changed=qt_widgets/tabwidget.rs");
|
||||
println!("cargo:rerun-if-changed=lib.rs");
|
||||
println!("cargo:SUPPORTS_NATIVE_STYLE=1");
|
||||
|
|
|
@ -201,100 +201,5 @@ pub use combobox::*;
|
|||
mod tabwidget;
|
||||
pub use tabwidget::*;
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(FieldOffsets, SixtyFPSElement)]
|
||||
#[pin]
|
||||
pub struct NativeStyleMetrics {
|
||||
pub layout_spacing: Property<f32>,
|
||||
pub layout_padding: Property<f32>,
|
||||
pub text_cursor_width: Property<f32>,
|
||||
pub window_background: Property<Color>,
|
||||
pub default_text_color: Property<Color>,
|
||||
pub textedit_background: Property<Color>,
|
||||
pub textedit_text_color: Property<Color>,
|
||||
pub textedit_background_disabled: Property<Color>,
|
||||
pub textedit_text_color_disabled: Property<Color>,
|
||||
|
||||
pub placeholder_color: Property<Color>,
|
||||
pub placeholder_color_disabled: Property<Color>,
|
||||
}
|
||||
|
||||
impl Default for NativeStyleMetrics {
|
||||
fn default() -> Self {
|
||||
let s = NativeStyleMetrics {
|
||||
layout_spacing: Default::default(),
|
||||
layout_padding: Default::default(),
|
||||
text_cursor_width: Default::default(),
|
||||
window_background: Default::default(),
|
||||
default_text_color: Default::default(),
|
||||
textedit_background: Default::default(),
|
||||
textedit_text_color: Default::default(),
|
||||
textedit_background_disabled: Default::default(),
|
||||
textedit_text_color_disabled: Default::default(),
|
||||
placeholder_color: Default::default(),
|
||||
placeholder_color_disabled: Default::default(),
|
||||
};
|
||||
sixtyfps_init_native_style_metrics(&s);
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeStyleMetrics {
|
||||
pub fn new() -> Pin<Rc<Self>> {
|
||||
Rc::pin(Self::default())
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize the native style metrics
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sixtyfps_init_native_style_metrics(self_: &NativeStyleMetrics) {
|
||||
let layout_spacing = cpp!(unsafe [] -> f32 as "float" {
|
||||
ensure_initialized();
|
||||
int spacing = qApp->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
|
||||
if (spacing < 0)
|
||||
spacing = qApp->style()->layoutSpacing(QSizePolicy::DefaultType, QSizePolicy::DefaultType, Qt::Horizontal);
|
||||
return spacing;
|
||||
});
|
||||
self_.layout_spacing.set(layout_spacing.max(0.0));
|
||||
let layout_padding = cpp!(unsafe [] -> f32 as "float" {
|
||||
ensure_initialized();
|
||||
return qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
|
||||
});
|
||||
self_.layout_padding.set(layout_padding.max(0.0));
|
||||
let text_cursor_width = cpp!(unsafe [] -> f32 as "float" {
|
||||
return qApp->style()->pixelMetric(QStyle::PM_TextCursorWidth);
|
||||
});
|
||||
self_.text_cursor_width.set(text_cursor_width.max(0.0));
|
||||
let window_background = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Window).rgba();
|
||||
});
|
||||
self_.window_background.set(Color::from_argb_encoded(window_background));
|
||||
let default_text_color = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::WindowText).rgba();
|
||||
});
|
||||
self_.default_text_color.set(Color::from_argb_encoded(default_text_color));
|
||||
let textedit_text_color = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Text).rgba();
|
||||
});
|
||||
self_.textedit_text_color.set(Color::from_argb_encoded(textedit_text_color));
|
||||
let textedit_text_color_disabled = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Disabled, QPalette::Text).rgba();
|
||||
});
|
||||
self_.textedit_text_color_disabled.set(Color::from_argb_encoded(textedit_text_color_disabled));
|
||||
let textedit_background = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Base).rgba();
|
||||
});
|
||||
self_.textedit_background.set(Color::from_argb_encoded(textedit_background));
|
||||
let textedit_background_disabled = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Disabled, QPalette::Base).rgba();
|
||||
});
|
||||
self_.textedit_background_disabled.set(Color::from_argb_encoded(textedit_background_disabled));
|
||||
let placeholder_color = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::PlaceholderText).rgba();
|
||||
});
|
||||
self_.placeholder_color.set(Color::from_argb_encoded(placeholder_color));
|
||||
let placeholder_color_disabled = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Disabled, QPalette::PlaceholderText).rgba();
|
||||
});
|
||||
self_.placeholder_color_disabled.set(Color::from_argb_encoded(placeholder_color_disabled));
|
||||
}
|
||||
mod stylemetrics;
|
||||
pub use stylemetrics::*;
|
||||
|
|
|
@ -0,0 +1,158 @@
|
|||
/* LICENSE BEGIN
|
||||
This file is part of the SixtyFPS Project -- https://sixtyfps.io
|
||||
Copyright (c) 2021 Olivier Goffart <olivier.goffart@sixtyfps.io>
|
||||
Copyright (c) 2021 Simon Hausmann <simon.hausmann@sixtyfps.io>
|
||||
|
||||
SPDX-License-Identifier: GPL-3.0-only
|
||||
This file is also available under commercial licensing terms.
|
||||
Please contact info@sixtyfps.io for more information.
|
||||
LICENSE END */
|
||||
|
||||
use super::*;
|
||||
|
||||
cpp! {{
|
||||
namespace {
|
||||
struct StyleChangeListener : QWidget {
|
||||
const void *nativeStyleMetrics = nullptr;
|
||||
StyleChangeListener(const void *nativeStyleMetrics) : nativeStyleMetrics(nativeStyleMetrics) {}
|
||||
bool event(QEvent *event) override {
|
||||
auto ty = event->type();
|
||||
if (ty == QEvent::StyleChange || ty == QEvent::PaletteChange || ty == QEvent::FontChange) {
|
||||
rust!(SFPS_style_change_event [nativeStyleMetrics: Pin<&NativeStyleMetrics> as "const void*"] {
|
||||
nativeStyleMetrics.init();
|
||||
});
|
||||
}
|
||||
return QWidget::event(event);
|
||||
}
|
||||
};
|
||||
}
|
||||
}}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(FieldOffsets, SixtyFPSElement)]
|
||||
#[pin]
|
||||
#[pin_drop]
|
||||
pub struct NativeStyleMetrics {
|
||||
pub layout_spacing: Property<f32>,
|
||||
pub layout_padding: Property<f32>,
|
||||
pub text_cursor_width: Property<f32>,
|
||||
pub window_background: Property<Color>,
|
||||
pub default_text_color: Property<Color>,
|
||||
pub textedit_background: Property<Color>,
|
||||
pub textedit_text_color: Property<Color>,
|
||||
pub textedit_background_disabled: Property<Color>,
|
||||
pub textedit_text_color_disabled: Property<Color>,
|
||||
|
||||
pub placeholder_color: Property<Color>,
|
||||
pub placeholder_color_disabled: Property<Color>,
|
||||
|
||||
pub style_change_listener: core::cell::Cell<*const u8>,
|
||||
}
|
||||
|
||||
impl const_field_offset::PinnedDrop for NativeStyleMetrics {
|
||||
fn drop(self: Pin<&mut Self>) {
|
||||
sixtyfps_native_style_metrics_deinit(self);
|
||||
}
|
||||
}
|
||||
|
||||
impl NativeStyleMetrics {
|
||||
pub fn new() -> Pin<Rc<Self>> {
|
||||
let new = Rc::pin(NativeStyleMetrics {
|
||||
layout_spacing: Default::default(),
|
||||
layout_padding: Default::default(),
|
||||
text_cursor_width: Default::default(),
|
||||
window_background: Default::default(),
|
||||
default_text_color: Default::default(),
|
||||
textedit_background: Default::default(),
|
||||
textedit_text_color: Default::default(),
|
||||
textedit_background_disabled: Default::default(),
|
||||
textedit_text_color_disabled: Default::default(),
|
||||
placeholder_color: Default::default(),
|
||||
placeholder_color_disabled: Default::default(),
|
||||
style_change_listener: core::cell::Cell::new(core::ptr::null()),
|
||||
});
|
||||
new.as_ref().init();
|
||||
new
|
||||
}
|
||||
|
||||
fn init(self: Pin<&Self>) {
|
||||
if self.style_change_listener.get().is_null() {
|
||||
self.style_change_listener.set(cpp!(unsafe [self as "void*"] -> *const u8 as "void*"{
|
||||
ensure_initialized();
|
||||
return new StyleChangeListener(self);
|
||||
}));
|
||||
}
|
||||
|
||||
let layout_spacing = cpp!(unsafe [] -> f32 as "float" {
|
||||
ensure_initialized();
|
||||
int spacing = qApp->style()->pixelMetric(QStyle::PM_LayoutHorizontalSpacing);
|
||||
if (spacing < 0)
|
||||
spacing = qApp->style()->layoutSpacing(QSizePolicy::DefaultType, QSizePolicy::DefaultType, Qt::Horizontal);
|
||||
return spacing;
|
||||
});
|
||||
self.layout_spacing.set(layout_spacing.max(0.0));
|
||||
let layout_padding = cpp!(unsafe [] -> f32 as "float" {
|
||||
ensure_initialized();
|
||||
return qApp->style()->pixelMetric(QStyle::PM_LayoutLeftMargin);
|
||||
});
|
||||
self.layout_padding.set(layout_padding.max(0.0));
|
||||
let text_cursor_width = cpp!(unsafe [] -> f32 as "float" {
|
||||
return qApp->style()->pixelMetric(QStyle::PM_TextCursorWidth);
|
||||
});
|
||||
self.text_cursor_width.set(text_cursor_width.max(0.0));
|
||||
let window_background = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Window).rgba();
|
||||
});
|
||||
self.window_background.set(Color::from_argb_encoded(window_background));
|
||||
let default_text_color = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::WindowText).rgba();
|
||||
});
|
||||
self.default_text_color.set(Color::from_argb_encoded(default_text_color));
|
||||
let textedit_text_color = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Text).rgba();
|
||||
});
|
||||
self.textedit_text_color.set(Color::from_argb_encoded(textedit_text_color));
|
||||
let textedit_text_color_disabled = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Disabled, QPalette::Text).rgba();
|
||||
});
|
||||
self.textedit_text_color_disabled
|
||||
.set(Color::from_argb_encoded(textedit_text_color_disabled));
|
||||
let textedit_background = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Base).rgba();
|
||||
});
|
||||
self.textedit_background.set(Color::from_argb_encoded(textedit_background));
|
||||
let textedit_background_disabled = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Disabled, QPalette::Base).rgba();
|
||||
});
|
||||
self.textedit_background_disabled
|
||||
.set(Color::from_argb_encoded(textedit_background_disabled));
|
||||
let placeholder_color = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::PlaceholderText).rgba();
|
||||
});
|
||||
self.placeholder_color.set(Color::from_argb_encoded(placeholder_color));
|
||||
let placeholder_color_disabled = cpp!(unsafe[] -> u32 as "QRgb" {
|
||||
return qApp->palette().color(QPalette::Disabled, QPalette::PlaceholderText).rgba();
|
||||
});
|
||||
self.placeholder_color_disabled.set(Color::from_argb_encoded(placeholder_color_disabled));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "rtti")]
|
||||
impl sixtyfps_corelib::rtti::BuiltinGlobal for NativeStyleMetrics {
|
||||
fn new() -> Pin<Rc<Self>> {
|
||||
NativeStyleMetrics::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sixtyfps_native_style_metrics_init(self_: Pin<&NativeStyleMetrics>) {
|
||||
self_.style_change_listener.set(core::ptr::null()); // because the C++ code don't initialize it
|
||||
self_.init();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn sixtyfps_native_style_metrics_deinit(self_: Pin<&mut NativeStyleMetrics>) {
|
||||
let scl = self_.style_change_listener.get();
|
||||
cpp!(unsafe [scl as "StyleChangeListener*"] { delete scl; });
|
||||
self_.style_change_listener.set(core::ptr::null());
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue