RADLib
RADical C++ application framework
RADSlintBackend.h
Go to the documentation of this file.
1 #ifndef RADSLINTBACKEND_H
2 #define RADSLINTBACKEND_H
3 
9 #pragma once
10 
11 #include <RADUi/RADUi.h>
12 #include <RADUi/RADTheme.h>
13 
14 #include <slint.h>
15 
16 #include <tuple>
17 #include <type_traits>
18 #include <utility>
19 
20 namespace RADUi::Slint {
21 
23  class SlintBackend : public RADUi::Backend {
24  public:
27 
29  void run() override;
31  void quit() override;
33  void postToUi(std::function<void()> task) override;
35  bool isUiThread() const override;
36 
37  private:
38  std::thread::id uiThreadId_;
39  };
40 
42  std::shared_ptr<SlintBackend> installBackend();
43 
45  template<typename Component, typename F>
46  void postToComponent(const slint::ComponentHandle<Component>& component, F&& action) {
47  slint::ComponentWeakHandle<Component> weakComponent(component);
48  RADUi::postToUi([weakComponent, action = std::forward<F>(action)]() mutable {
49  if (auto componentHandle = weakComponent.lock()) {
50  action(*componentHandle);
51  }
52  });
53  }
54 
55  namespace Detail {
57  template<typename Component, typename Callback, typename... Args>
59  public:
62  RADCore::Event<void(Args...)>& event,
63  const slint::ComponentHandle<Component>& component,
64  Callback callback)
65  : weakComponent_(component), callback_(std::move(callback)) {
66  connection_ = event.connect(this, &EventComponentBridge::handle);
67  }
68 
70  void handle(Args... args) {
71  using StoredArgs = std::tuple<std::decay_t<Args>...>;
72  StoredArgs storedArgs(std::forward<Args>(args)...);
73  auto weakComponent = weakComponent_;
74  auto callback = callback_;
75 
76  RADUi::postToUi([weakComponent, callback, storedArgs = std::move(storedArgs)]() mutable {
77  if (auto componentHandle = weakComponent.lock()) {
78  std::apply([&](auto&&... unpacked) {
79  callback(*componentHandle, std::forward<decltype(unpacked)>(unpacked)...);
80  }, std::move(storedArgs));
81  }
82  });
83  }
84 
85  private:
86  slint::ComponentWeakHandle<Component> weakComponent_;
87  Callback callback_;
88  RADCore::Connection connection_;
89  };
90 
92  template<typename Component, typename Callback>
94  public:
97  RADUi::ThemeManager& manager,
98  const slint::ComponentHandle<Component>& component,
99  Callback callback)
100  : manager_(manager), weakComponent_(component), callback_(std::move(callback)) {
101  connection_ = manager_.changed.connect(this, &ThemeComponentBridge::handle);
102  handle();
103  }
104 
106  void handle() {
107  auto weakComponent = weakComponent_;
108  auto callback = callback_;
109  auto theme = manager_.theme();
110  RADUi::postToUi([weakComponent, callback, theme = std::move(theme)]() mutable {
111  if (auto componentHandle = weakComponent.lock()) {
112  callback(*componentHandle, theme);
113  }
114  });
115  }
116 
117  private:
118  RADUi::ThemeManager& manager_;
119  slint::ComponentWeakHandle<Component> weakComponent_;
120  Callback callback_;
121  RADCore::Connection connection_;
122  };
123  } // namespace Detail
124 
126  template<typename Component, typename... Args, typename F>
128  RADCore::Event<void(Args...)>& event,
129  const slint::ComponentHandle<Component>& component,
130  F&& callback) {
132  return RADUi::Binding(std::make_shared<Bridge>(event, component, std::forward<F>(callback)));
133  }
134 
136  template<typename Component, typename... Args, typename F>
138  RADCore::Event<void(Args...)>& event,
139  const slint::ComponentHandle<Component>& component,
140  F&& callback) {
141  return connectEventToComponent(event, component, std::forward<F>(callback));
142  }
143 
145  template<typename Component, typename Value, typename Setter>
147  RADCore::Event<void(Value)>& event,
148  const slint::ComponentHandle<Component>& component,
149  Setter setter) {
150  return bindEventToComponent(event, component,
151  [setter](auto componentHandle, Value value) mutable {
152  ((*componentHandle).*setter)(std::move(value));
153  });
154  }
155 
157  template<typename Component, typename Value, typename Setter, typename Transform>
159  RADCore::Event<void(Value)>& event,
160  const slint::ComponentHandle<Component>& component,
161  Setter setter,
162  Transform transform) {
163  return bindEventToComponent(event, component,
164  [setter, transform = std::move(transform)](auto componentHandle, Value value) mutable {
165  ((*componentHandle).*setter)(transform(std::move(value)));
166  });
167  }
168 
170  template<typename Component, typename F>
172  RADUi::ThemeManager& manager,
173  const slint::ComponentHandle<Component>& component,
174  F&& callback) {
176  return RADUi::Binding(std::make_shared<Bridge>(manager, component, std::forward<F>(callback)));
177  }
178 
179 } // namespace RADUi::Slint
180 
181 #endif
Explicit event connection handle.
Definition: RADCore.h:903
Typed event template; use RAD_EVENT to declare instances.
Definition: RADCore.h:874
Base class for event receivers, senders, and thread-affinity aware objects.
Definition: RADCore.h:931
Abstract UI backend used to post tasks to a toolkit UI thread.
Definition: RADUi.h:45
RAII-style binding handle that keeps a bridge object alive until disconnected.
Definition: RADUi.h:28
Bridge object that forwards RADCore events to a Slint component callback.
Definition: RADSlintBackend.h:58
EventComponentBridge(RADCore::Event< void(Args...)> &event, const slint::ComponentHandle< Component > &component, Callback callback)
Connects event and stores a weak component reference.
Definition: RADSlintBackend.h:61
void handle(Args... args)
Handles the RAD event and posts callback invocation to the UI thread.
Definition: RADSlintBackend.h:70
Bridge object that forwards ThemeManager changes to a Slint component callback.
Definition: RADSlintBackend.h:93
ThemeComponentBridge(RADUi::ThemeManager &manager, const slint::ComponentHandle< Component > &component, Callback callback)
Connects manager and stores a weak component reference.
Definition: RADSlintBackend.h:96
void handle()
Posts current theme tokens to the component.
Definition: RADSlintBackend.h:106
RADUi backend implementation that uses Slint's event loop.
Definition: RADSlintBackend.h:23
SlintBackend()
Captures the creating thread as the UI thread.
void postToUi(std::function< void()> task) override
Posts task to Slint's UI queue.
bool isUiThread() const override
Returns true when called from the captured UI thread.
void run() override
Runs Slint's main event loop.
void quit() override
Requests Slint's event loop to quit.
Process/application theme manager with RADCore events.
Definition: RADTheme.h:103
Definition: RADSlintBackend.h:20
std::shared_ptr< SlintBackend > installBackend()
Installs and returns a shared Slint backend for RADUi.
RADUi::Binding bindTheme(RADUi::ThemeManager &manager, const slint::ComponentHandle< Component > &component, F &&callback)
Binds ThemeManager changes to a generated Slint component callback.
Definition: RADSlintBackend.h:171
RADUi::Binding bindEventToComponent(RADCore::Event< void(Args...)> &event, const slint::ComponentHandle< Component > &component, F &&callback)
Alias for connectEventToComponent used by property-oriented bridge code.
Definition: RADSlintBackend.h:137
RADUi::Binding connectEventToComponent(RADCore::Event< void(Args...)> &event, const slint::ComponentHandle< Component > &component, F &&callback)
Connects a RADCore event to a Slint component callback and returns a binding handle.
Definition: RADSlintBackend.h:127
RADUi::Binding bindProperty(RADCore::Event< void(Value)> &event, const slint::ComponentHandle< Component > &component, Setter setter, Transform transform)
Binds an event value to a generated Slint property setter after transform.
Definition: RADSlintBackend.h:158
void postToComponent(const slint::ComponentHandle< Component > &component, F &&action)
Posts action to the UI thread and invokes it only if component is still alive.
Definition: RADSlintBackend.h:46
void postToUi(std::function< void()> task)
Posts task to the installed UI backend.