color picker and palette editor
git clone https://git.lucas.co/cce-color-editor.git
refactor: hold widgets in Owned boxes (cce-ui Owned<W>)
The UiContext registry keeps raw pointers to registered widgets, and a
widget that moved while registered (its Vec reallocating, its struct
returned by value) left one pointing at the old address. Each widget
field is now an Owned<Adapted<..>> — a heap box whose allocation, not the
widget, carries the liveness token the registry watches — so the
registered address never moves and is dropped from the registry when the
box is freed. Field access is unchanged through Deref; construction
sites wrap in Owned::new.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
src/main.rs | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/main.rs b/src/main.rs
index ae7e3bf..5b5a4fe 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,3 +1,4 @@
+use cce_ui::widget::Owned;
use cce_ui::engine::{Application, WindowSettings, LogicalSize, LogicalPosition, EngineState};
use cce_ui::widget::{
Adapted, Button, WidgetHost, EventCtx, UiContext, MouseButton, ElementState, KeyEvent,
@@ -405,9 +406,9 @@ enum Message {
// ── ColorApp State ───────────────────────────────────────────────────
struct ColorApp {
- apply_btn: cce_ui::widget::Adapted<cce_ui::widget::Button>,
- cancel_btn: cce_ui::widget::Adapted<cce_ui::widget::Button>,
- sliders: Vec<Adapted<ColorSlider>>,
+ apply_btn: Owned<cce_ui::widget::Adapted<cce_ui::widget::Button>>,
+ cancel_btn: Owned<cce_ui::widget::Adapted<cce_ui::widget::Button>>,
+ sliders: Vec<Owned<Adapted<ColorSlider>>>,
red: f32,
green: f32,
@@ -741,9 +742,9 @@ impl Application for ColorApp {
}
let mut app = Self {
- apply_btn,
- cancel_btn,
- sliders,
+ apply_btn: Owned::new(apply_btn),
+ cancel_btn: Owned::new(cancel_btn),
+ sliders: sliders.into_iter().map(Owned::new).collect(),
red: r,
green: g,
blue: b,