i_slint_backend_qt/qt_widgets/
button.rs

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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0

// cSpell: ignore qstyle unshade

use super::*;

#[allow(nonstandard_style)]
#[allow(unused)]
mod standard_button {
    // Generated with
    // bindgen /usr/include/qt/QtWidgets/qstyle.h  --whitelist-type QStyle -- -I /usr/include/qt -xc++ | grep _StandardPixmap_ -A1
    pub const QStyle_StandardPixmap_SP_TitleBarMenuButton: QStyle_StandardPixmap = 0;
    pub const QStyle_StandardPixmap_SP_TitleBarMinButton: QStyle_StandardPixmap = 1;
    pub const QStyle_StandardPixmap_SP_TitleBarMaxButton: QStyle_StandardPixmap = 2;
    pub const QStyle_StandardPixmap_SP_TitleBarCloseButton: QStyle_StandardPixmap = 3;
    pub const QStyle_StandardPixmap_SP_TitleBarNormalButton: QStyle_StandardPixmap = 4;
    pub const QStyle_StandardPixmap_SP_TitleBarShadeButton: QStyle_StandardPixmap = 5;
    pub const QStyle_StandardPixmap_SP_TitleBarUnshadeButton: QStyle_StandardPixmap = 6;
    pub const QStyle_StandardPixmap_SP_TitleBarContextHelpButton: QStyle_StandardPixmap = 7;
    pub const QStyle_StandardPixmap_SP_DockWidgetCloseButton: QStyle_StandardPixmap = 8;
    pub const QStyle_StandardPixmap_SP_MessageBoxInformation: QStyle_StandardPixmap = 9;
    pub const QStyle_StandardPixmap_SP_MessageBoxWarning: QStyle_StandardPixmap = 10;
    pub const QStyle_StandardPixmap_SP_MessageBoxCritical: QStyle_StandardPixmap = 11;
    pub const QStyle_StandardPixmap_SP_MessageBoxQuestion: QStyle_StandardPixmap = 12;
    pub const QStyle_StandardPixmap_SP_DesktopIcon: QStyle_StandardPixmap = 13;
    pub const QStyle_StandardPixmap_SP_TrashIcon: QStyle_StandardPixmap = 14;
    pub const QStyle_StandardPixmap_SP_ComputerIcon: QStyle_StandardPixmap = 15;
    pub const QStyle_StandardPixmap_SP_DriveFDIcon: QStyle_StandardPixmap = 16;
    pub const QStyle_StandardPixmap_SP_DriveHDIcon: QStyle_StandardPixmap = 17;
    pub const QStyle_StandardPixmap_SP_DriveCDIcon: QStyle_StandardPixmap = 18;
    pub const QStyle_StandardPixmap_SP_DriveDVDIcon: QStyle_StandardPixmap = 19;
    pub const QStyle_StandardPixmap_SP_DriveNetIcon: QStyle_StandardPixmap = 20;
    pub const QStyle_StandardPixmap_SP_DirOpenIcon: QStyle_StandardPixmap = 21;
    pub const QStyle_StandardPixmap_SP_DirClosedIcon: QStyle_StandardPixmap = 22;
    pub const QStyle_StandardPixmap_SP_DirLinkIcon: QStyle_StandardPixmap = 23;
    pub const QStyle_StandardPixmap_SP_DirLinkOpenIcon: QStyle_StandardPixmap = 24;
    pub const QStyle_StandardPixmap_SP_FileIcon: QStyle_StandardPixmap = 25;
    pub const QStyle_StandardPixmap_SP_FileLinkIcon: QStyle_StandardPixmap = 26;
    pub const QStyle_StandardPixmap_SP_ToolBarHorizontalExtensionButton: QStyle_StandardPixmap = 27;
    pub const QStyle_StandardPixmap_SP_ToolBarVerticalExtensionButton: QStyle_StandardPixmap = 28;
    pub const QStyle_StandardPixmap_SP_FileDialogStart: QStyle_StandardPixmap = 29;
    pub const QStyle_StandardPixmap_SP_FileDialogEnd: QStyle_StandardPixmap = 30;
    pub const QStyle_StandardPixmap_SP_FileDialogToParent: QStyle_StandardPixmap = 31;
    pub const QStyle_StandardPixmap_SP_FileDialogNewFolder: QStyle_StandardPixmap = 32;
    pub const QStyle_StandardPixmap_SP_FileDialogDetailedView: QStyle_StandardPixmap = 33;
    pub const QStyle_StandardPixmap_SP_FileDialogInfoView: QStyle_StandardPixmap = 34;
    pub const QStyle_StandardPixmap_SP_FileDialogContentsView: QStyle_StandardPixmap = 35;
    pub const QStyle_StandardPixmap_SP_FileDialogListView: QStyle_StandardPixmap = 36;
    pub const QStyle_StandardPixmap_SP_FileDialogBack: QStyle_StandardPixmap = 37;
    pub const QStyle_StandardPixmap_SP_DirIcon: QStyle_StandardPixmap = 38;
    pub const QStyle_StandardPixmap_SP_DialogOkButton: QStyle_StandardPixmap = 39;
    pub const QStyle_StandardPixmap_SP_DialogCancelButton: QStyle_StandardPixmap = 40;
    pub const QStyle_StandardPixmap_SP_DialogHelpButton: QStyle_StandardPixmap = 41;
    pub const QStyle_StandardPixmap_SP_DialogOpenButton: QStyle_StandardPixmap = 42;
    pub const QStyle_StandardPixmap_SP_DialogSaveButton: QStyle_StandardPixmap = 43;
    pub const QStyle_StandardPixmap_SP_DialogCloseButton: QStyle_StandardPixmap = 44;
    pub const QStyle_StandardPixmap_SP_DialogApplyButton: QStyle_StandardPixmap = 45;
    pub const QStyle_StandardPixmap_SP_DialogResetButton: QStyle_StandardPixmap = 46;
    pub const QStyle_StandardPixmap_SP_DialogDiscardButton: QStyle_StandardPixmap = 47;
    pub const QStyle_StandardPixmap_SP_DialogYesButton: QStyle_StandardPixmap = 48;
    pub const QStyle_StandardPixmap_SP_DialogNoButton: QStyle_StandardPixmap = 49;
    pub const QStyle_StandardPixmap_SP_ArrowUp: QStyle_StandardPixmap = 50;
    pub const QStyle_StandardPixmap_SP_ArrowDown: QStyle_StandardPixmap = 51;
    pub const QStyle_StandardPixmap_SP_ArrowLeft: QStyle_StandardPixmap = 52;
    pub const QStyle_StandardPixmap_SP_ArrowRight: QStyle_StandardPixmap = 53;
    pub const QStyle_StandardPixmap_SP_ArrowBack: QStyle_StandardPixmap = 54;
    pub const QStyle_StandardPixmap_SP_ArrowForward: QStyle_StandardPixmap = 55;
    pub const QStyle_StandardPixmap_SP_DirHomeIcon: QStyle_StandardPixmap = 56;
    pub const QStyle_StandardPixmap_SP_CommandLink: QStyle_StandardPixmap = 57;
    pub const QStyle_StandardPixmap_SP_VistaShield: QStyle_StandardPixmap = 58;
    pub const QStyle_StandardPixmap_SP_BrowserReload: QStyle_StandardPixmap = 59;
    pub const QStyle_StandardPixmap_SP_BrowserStop: QStyle_StandardPixmap = 60;
    pub const QStyle_StandardPixmap_SP_MediaPlay: QStyle_StandardPixmap = 61;
    pub const QStyle_StandardPixmap_SP_MediaStop: QStyle_StandardPixmap = 62;
    pub const QStyle_StandardPixmap_SP_MediaPause: QStyle_StandardPixmap = 63;
    pub const QStyle_StandardPixmap_SP_MediaSkipForward: QStyle_StandardPixmap = 64;
    pub const QStyle_StandardPixmap_SP_MediaSkipBackward: QStyle_StandardPixmap = 65;
    pub const QStyle_StandardPixmap_SP_MediaSeekForward: QStyle_StandardPixmap = 66;
    pub const QStyle_StandardPixmap_SP_MediaSeekBackward: QStyle_StandardPixmap = 67;
    pub const QStyle_StandardPixmap_SP_MediaVolume: QStyle_StandardPixmap = 68;
    pub const QStyle_StandardPixmap_SP_MediaVolumeMuted: QStyle_StandardPixmap = 69;
    pub const QStyle_StandardPixmap_SP_LineEditClearButton: QStyle_StandardPixmap = 70;
    pub const QStyle_StandardPixmap_SP_DialogYesToAllButton: QStyle_StandardPixmap = 71;
    pub const QStyle_StandardPixmap_SP_DialogNoToAllButton: QStyle_StandardPixmap = 72;
    pub const QStyle_StandardPixmap_SP_DialogSaveAllButton: QStyle_StandardPixmap = 73;
    pub const QStyle_StandardPixmap_SP_DialogAbortButton: QStyle_StandardPixmap = 74;
    pub const QStyle_StandardPixmap_SP_DialogRetryButton: QStyle_StandardPixmap = 75;
    pub const QStyle_StandardPixmap_SP_DialogIgnoreButton: QStyle_StandardPixmap = 76;
    pub const QStyle_StandardPixmap_SP_RestoreDefaultsButton: QStyle_StandardPixmap = 77;
    pub const QStyle_StandardPixmap_SP_CustomBase: QStyle_StandardPixmap = 4026531840;
    pub type QStyle_StandardPixmap = ::std::os::raw::c_uint;
}

use i_slint_core::{
    input::{FocusEventResult, KeyEventType},
    items::StandardButtonKind,
    platform::PointerEventButton,
};
use standard_button::*;

type ActualStandardButtonKind = Option<StandardButtonKind>;

#[repr(C)]
#[derive(FieldOffsets, Default, SlintElement)]
#[pin]
pub struct NativeButton {
    pub text: Property<SharedString>,
    pub icon: Property<i_slint_core::graphics::Image>,
    pub pressed: Property<bool>,
    pub has_hover: Property<bool>,
    pub checkable: Property<bool>,
    pub checked: Property<bool>,
    pub primary: Property<bool>,
    pub has_focus: Property<bool>,
    pub clicked: Callback<VoidArg>,
    pub enabled: Property<bool>,
    pub colorize_icon: Property<bool>,
    pub standard_button_kind: Property<StandardButtonKind>,
    pub is_standard_button: Property<bool>,
    widget_ptr: std::cell::Cell<SlintTypeErasedWidgetPtr>,
    animation_tracker: Property<i32>,
    pub cached_rendering_data: CachedRenderingData,
}

impl NativeButton {
    fn actual_standard_button_kind(self: Pin<&Self>) -> ActualStandardButtonKind {
        self.is_standard_button().then(|| self.standard_button_kind())
    }

    fn actual_text(
        self: Pin<&Self>,
        standard_button_kind: ActualStandardButtonKind,
    ) -> qttypes::QString {
        // We would need to use the private API to get the text from QPlatformTheme
        match standard_button_kind {
            Some(StandardButtonKind::Ok) => "OK".into(),
            Some(StandardButtonKind::Cancel) => "Cancel".into(),
            Some(StandardButtonKind::Apply) => "Apply".into(),
            Some(StandardButtonKind::Close) => "Close".into(),
            Some(StandardButtonKind::Reset) => "Reset".into(),
            Some(StandardButtonKind::Help) => "Help".into(),
            Some(StandardButtonKind::Yes) => "Yes".into(),
            Some(StandardButtonKind::No) => "No".into(),
            Some(StandardButtonKind::Abort) => "Abort".into(),
            Some(StandardButtonKind::Retry) => "Retry".into(),
            Some(StandardButtonKind::Ignore) => "Ignore".into(),
            None => self.text().as_str().into(),
        }
    }

    fn actual_icon(
        self: Pin<&Self>,
        standard_button_kind: ActualStandardButtonKind,
    ) -> qttypes::QPixmap {
        let style_icon = match standard_button_kind {
            Some(StandardButtonKind::Ok) => QStyle_StandardPixmap_SP_DialogOkButton,
            Some(StandardButtonKind::Cancel) => QStyle_StandardPixmap_SP_DialogCancelButton,
            Some(StandardButtonKind::Apply) => QStyle_StandardPixmap_SP_DialogApplyButton,
            Some(StandardButtonKind::Close) => QStyle_StandardPixmap_SP_DialogCloseButton,
            Some(StandardButtonKind::Reset) => QStyle_StandardPixmap_SP_DialogResetButton,
            Some(StandardButtonKind::Help) => QStyle_StandardPixmap_SP_DialogHelpButton,
            Some(StandardButtonKind::Yes) => QStyle_StandardPixmap_SP_DialogYesButton,
            Some(StandardButtonKind::No) => QStyle_StandardPixmap_SP_DialogNoButton,
            Some(StandardButtonKind::Abort) => QStyle_StandardPixmap_SP_DialogAbortButton,
            Some(StandardButtonKind::Retry) => QStyle_StandardPixmap_SP_DialogRetryButton,
            Some(StandardButtonKind::Ignore) => QStyle_StandardPixmap_SP_DialogIgnoreButton,
            None => {
                return crate::qt_window::image_to_pixmap((&self.icon()).into(), None)
                    .unwrap_or_default();
            }
        };
        let widget_ptr: NonNull<()> = SlintTypeErasedWidgetPtr::qwidget_ptr(&self.widget_ptr);
        cpp!(unsafe [style_icon as "QStyle::StandardPixmap", widget_ptr as "QWidget*"] -> qttypes::QPixmap as "QPixmap" {
            ensure_initialized();
            auto style = qApp->style();
            if (!style->styleHint(QStyle::SH_DialogButtonBox_ButtonsHaveIcons, nullptr, widget_ptr))
                return QPixmap();
            return style->standardPixmap(style_icon);
        })
    }

    fn activate(self: Pin<&Self>) {
        Self::FIELD_OFFSETS.pressed.apply_pin(self).set(false);
        if self.checkable() {
            let checked = Self::FIELD_OFFSETS.checked.apply_pin(self);
            checked.set(!checked.get());
        }
        Self::FIELD_OFFSETS.clicked.apply_pin(self).call(&());
    }
}

impl Item for NativeButton {
    fn init(self: Pin<&Self>, _self_rc: &ItemRc) {
        let animation_tracker_property_ptr = Self::FIELD_OFFSETS.animation_tracker.apply_pin(self);
        self.widget_ptr.set(cpp! { unsafe [animation_tracker_property_ptr as "void*"] -> SlintTypeErasedWidgetPtr as "std::unique_ptr<SlintTypeErasedWidget>" {
            return make_unique_animated_widget<QPushButton>(animation_tracker_property_ptr);
        }})
    }

    fn layout_info(
        self: Pin<&Self>,
        orientation: Orientation,
        _window_adapter: &Rc<dyn WindowAdapter>,
    ) -> LayoutInfo {
        let standard_button_kind = self.actual_standard_button_kind();
        let mut text: qttypes::QString = self.actual_text(standard_button_kind);
        let icon: qttypes::QPixmap = self.actual_icon(standard_button_kind);
        let widget_ptr: NonNull<()> = SlintTypeErasedWidgetPtr::qwidget_ptr(&self.widget_ptr);
        let size = cpp!(unsafe [
            mut text as "QString",
            icon as "QPixmap",
            widget_ptr as "QWidget*"
        ] -> qttypes::QSize as "QSize" {
            ensure_initialized();
            QStyleOptionButton option;
            if (text.isEmpty())
                text = "**";
            option.rect = option.fontMetrics.boundingRect(text);
            option.text = std::move(text);
            option.icon = icon;
            auto iconSize = qApp->style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, widget_ptr);
            option.iconSize = QSize(iconSize, iconSize);
            if (!icon.isNull()) {
                option.rect.setHeight(qMax(option.rect.height(), iconSize));
                option.rect.setWidth(option.rect.width() + 4 + iconSize);
            }
            return qApp->style()->sizeFromContents(QStyle::CT_PushButton, &option, option.rect.size(), widget_ptr);
        });
        let min = match orientation {
            Orientation::Horizontal => size.width as f32,
            Orientation::Vertical => size.height as f32,
        };
        LayoutInfo { min, preferred: min, ..LayoutInfo::default() }
    }

    fn input_event_filter_before_children(
        self: Pin<&Self>,
        event: MouseEvent,
        _window_adapter: &Rc<dyn WindowAdapter>,
        _self_rc: &ItemRc,
    ) -> InputEventFilterResult {
        Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(!matches!(event, MouseEvent::Exit));
        InputEventFilterResult::ForwardEvent
    }

    fn input_event(
        self: Pin<&Self>,
        event: MouseEvent,
        _window_adapter: &Rc<dyn WindowAdapter>,
        self_rc: &i_slint_core::items::ItemRc,
    ) -> InputEventResult {
        if matches!(event, MouseEvent::Exit) {
            Self::FIELD_OFFSETS.has_hover.apply_pin(self).set(false);
        }
        let enabled = self.enabled();
        if !enabled {
            return InputEventResult::EventIgnored;
        }

        let was_pressed = self.pressed();

        Self::FIELD_OFFSETS.pressed.apply_pin(self).set(match event {
            MouseEvent::Pressed { button, .. } => button == PointerEventButton::Left,
            MouseEvent::Exit | MouseEvent::Released { .. } => false,
            MouseEvent::Moved { .. } => {
                return if was_pressed {
                    InputEventResult::GrabMouse
                } else {
                    InputEventResult::EventAccepted
                }
            }
            MouseEvent::Wheel { .. } => return InputEventResult::EventIgnored,
        });
        if let MouseEvent::Released { position, .. } = event {
            let geo = self_rc.geometry();
            if LogicalRect::new(LogicalPoint::default(), geo.size).contains(position) && was_pressed
            {
                self.activate();
            }
            InputEventResult::EventAccepted
        } else {
            InputEventResult::GrabMouse
        }
    }

    fn key_event(
        self: Pin<&Self>,
        event: &KeyEvent,
        _window_adapter: &Rc<dyn WindowAdapter>,
        _self_rc: &ItemRc,
    ) -> KeyEventResult {
        match event.event_type {
            KeyEventType::KeyPressed if event.text == " " || event.text == "\n" => {
                Self::FIELD_OFFSETS.pressed.apply_pin(self).set(true);
                KeyEventResult::EventAccepted
            }
            KeyEventType::KeyPressed => KeyEventResult::EventIgnored,
            KeyEventType::KeyReleased if event.text == " " || event.text == "\n" => {
                self.activate();
                KeyEventResult::EventAccepted
            }
            KeyEventType::KeyReleased => KeyEventResult::EventIgnored,
            KeyEventType::UpdateComposition | KeyEventType::CommitComposition => {
                KeyEventResult::EventIgnored
            }
        }
    }

    fn focus_event(
        self: Pin<&Self>,
        event: &FocusEvent,
        _window_adapter: &Rc<dyn WindowAdapter>,
        _self_rc: &ItemRc,
    ) -> FocusEventResult {
        if self.enabled() {
            Self::FIELD_OFFSETS
                .has_focus
                .apply_pin(self)
                .set(event == &FocusEvent::FocusIn || event == &FocusEvent::WindowReceivedFocus);
            FocusEventResult::FocusAccepted
        } else {
            FocusEventResult::FocusIgnored
        }
    }

    fn_render! { this dpr size painter widget initial_state =>
        let down: bool = this.pressed();
        let checked: bool = this.checked();
        let standard_button_kind = this.actual_standard_button_kind();
        let text: qttypes::QString = this.actual_text(standard_button_kind);
        let icon: qttypes::QPixmap = this.actual_icon(standard_button_kind);
        let enabled = this.enabled();
        let has_focus = this.has_focus();
        let has_hover = this.has_hover();
        let primary = this.primary();
        let colorize_icon = this.colorize_icon();

        cpp!(unsafe [
            painter as "QPainterPtr*",
            widget as "QWidget*",
            text as "QString",
            icon as "QPixmap",
            enabled as "bool",
            size as "QSize",
            down as "bool",
            checked as "bool",
            has_focus as "bool",
            has_hover as "bool",
            primary as "bool",
            colorize_icon as "bool",
            dpr as "float",
            initial_state as "int"
        ] {
            class ColorizedIconEngine : public QIconEngine
            {
            public:
                ColorizedIconEngine(const QIcon &icon, const QColor &color) : m_icon(icon), m_color(color) { }

                QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override
                {
                    QPixmap iconPixmap = m_icon.pixmap(size, mode, state);
                    if (!iconPixmap.isNull()) {
                        QPainter colorizePainter(&iconPixmap);
                        colorizePainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
                        colorizePainter.fillRect(iconPixmap.rect(), m_color);
                    }
                    return iconPixmap;
                }

                void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) override
                {
                    painter->drawPixmap(rect, this->pixmap(rect.size(), mode, state));
                }

                QIconEngine *clone() const override { return new ColorizedIconEngine(m_icon, m_color); }

            private:
                QIcon m_icon;
                QColor m_color;
            };

            QStyleOptionButton option;
            option.styleObject = widget;
            option.state |= QStyle::State(initial_state);
            option.text = std::move(text);

            QColor iconColor = qApp->palette().color(QPalette::ButtonText).rgba();

            if (down) {
                option.state |= QStyle::State_Sunken;
            } else {
                option.state |= QStyle::State_Raised;
            }
            if (checked) {
                option.state |= QStyle::State_On;
            }
            if (enabled) {
                option.state |= QStyle::State_Enabled;
            } else {
                option.palette.setCurrentColorGroup(QPalette::Disabled);
                iconColor = qApp->palette().color(QPalette::Disabled, QPalette::ButtonText).rgba();
            }
            if (has_focus) {
                option.state |= QStyle::State_HasFocus | QStyle::State_KeyboardFocusChange | QStyle::State_Item;
            }
            if (has_hover) {
                option.state |= QStyle::State_MouseOver;
            }
            if (primary) {
                option.features |= QStyleOptionButton::DefaultButton;
            }
            if (colorize_icon) {
                option.icon = QIcon(new ColorizedIconEngine(icon, iconColor));
            } else {
                option.icon = icon;
            }
            auto iconSize = qApp->style()->pixelMetric(QStyle::PM_ButtonIconSize, 0, nullptr);
            option.iconSize = QSize(iconSize, iconSize);
            option.rect = QRect(QPoint(), size / dpr);

            qApp->style()->drawControl(QStyle::CE_PushButton, &option, painter->get(), widget);
        });
    }
}

impl ItemConsts for NativeButton {
    const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
        Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
}

declare_item_vtable! {
    fn slint_get_NativeButtonVTable() -> NativeButtonVTable for NativeButton
}