#![allow(non_upper_case_globals)]
use const_field_offset::FieldOffsets;
use core::pin::Pin;
use cpp::cpp;
use sixtyfps_corelib::graphics::{Color, Rect};
use sixtyfps_corelib::input::{
FocusEvent, InputEventFilterResult, InputEventResult, KeyEvent, KeyEventResult, MouseEvent,
};
use sixtyfps_corelib::item_rendering::{CachedRenderingData, ItemRenderer};
use sixtyfps_corelib::items::{Item, ItemConsts, ItemRc, ItemVTable, VoidArg};
use sixtyfps_corelib::layout::{LayoutInfo, Orientation};
use sixtyfps_corelib::rtti::*;
use sixtyfps_corelib::window::WindowRc;
use sixtyfps_corelib::{
declare_item_vtable, Callback, ItemVTable_static, Property, SharedString, SharedVector,
};
use sixtyfps_corelib_macros::*;
use std::rc::Rc;
type ItemRendererRef<'a> = &'a mut dyn ItemRenderer;
use crate::qt_window::QPainter;
macro_rules! get_size {
($self:ident) => {{
let width = $self.width();
let height = $self.height();
if width < 1. || height < 1. {
return Default::default();
};
qttypes::QSize { width: width as _, height: height as _ }
}};
}
macro_rules! fn_render {
($this:ident $dpr:ident $size:ident $painter:ident $widget:ident $initial_state:ident => $($tt:tt)*) => {
fn render(self: Pin<&Self>, backend: &mut &mut dyn ItemRenderer) {
let $dpr: f32 = backend.scale_factor();
let window = backend.window();
let active: bool = window.active();
let $initial_state = cpp!(unsafe [ active as "bool" ] -> i32 as "int" {
QStyle::State state(QStyle::State_None);
if (active)
state |= QStyle::State_Active;
return (int)state;
});
if let Some(painter) = <dyn std::any::Any>::downcast_mut::<QPainter>(backend.as_any()) {
let $size: qttypes::QSize = get_size!(self);
let $this = self;
painter.save_state();
let $widget = cpp!(unsafe [painter as "QPainter*"] -> * const () as "QWidget*" {
return painter->device()->devType() == QInternal::Widget ? static_cast<QWidget *>(painter->device()) : nullptr;
});
let $painter = painter;
$($tt)*
$painter.restore_state();
} else {
backend.draw_cached_pixmap(
&self.cached_rendering_data,
&|callback| {
let width = self.width() * $dpr;
let height = self.height() * $dpr;
if width < 1. || height < 1. {
return Default::default();
};
let $size = qttypes::QSize { width: width as _, height: height as _ };
let mut imgarray = QImageWrapArray::new($size, $dpr);
let img = &mut imgarray.img;
let mut painter_ = cpp!(unsafe [img as "QImage*"] -> QPainter as "QPainter" { return QPainter(img); });
let $widget: * const () = core::ptr::null();
let $painter = &mut painter_;
let $this = self;
$($tt)*
drop(painter_);
imgarray.draw(callback);
},
);
}
}
};
}
struct QImageWrapArray {
img: qttypes::QImage,
array: SharedVector<u8>,
}
impl QImageWrapArray {
pub fn new(size: qttypes::QSize, dpr: f32) -> Self {
let mut array = SharedVector::default();
array.resize((size.width * size.height * 4) as usize, 0);
let array_ptr = array.make_mut_slice().as_mut_ptr();
let img = cpp!(unsafe [size as "QSize", array_ptr as "uchar*", dpr as "float"] -> qttypes::QImage as "QImage" {
ensure_initialized();
QImage img(array_ptr, size.width(), size.height(), size.width() * 4, QImage::Format_RGBA8888_Premultiplied);
img.setDevicePixelRatio(dpr);
return img;
});
QImageWrapArray { img, array }
}
pub fn draw(&self, callback: &mut dyn FnMut(u32, u32, &[u8])) {
let size = self.img.size();
callback(size.width, size.height, self.array.as_slice());
}
}
cpp! {{
#include <QtWidgets/QApplication>
#include <QtWidgets/QStyle>
#include <QtWidgets/QStyleOption>
#include <QtWidgets/QStyleFactory>
#include <QtGui/QPainter>
#include <QtGui/QClipboard>
#include <QtCore/QMimeData>
#include <QtCore/QDebug>
#include <QtCore/QScopeGuard>
void ensure_initialized()
{
static auto app [[maybe_unused]] = []{
if (qApp) {
return qApp;
}
QCoreApplication::setAttribute(Qt::AA_PluginApplication, true);
static int argc = 1;
static char argv[] = "sixtyfps";
static char *argv2[] = { argv };
return new QApplication(argc, argv2);
}();
}
}}
mod button;
pub use button::*;
mod checkbox;
pub use checkbox::*;
mod spinbox;
pub use spinbox::*;
mod slider;
pub use slider::*;
mod groupbox;
pub use groupbox::*;
mod lineedit;
pub use lineedit::*;
mod scrollview;
pub use scrollview::*;
mod listviewitem;
pub use listviewitem::*;
mod combobox;
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())
}
}
#[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));
}