1use gpui::{
2 App, Bounds, Context, Half, Hsla, Pixels, Point, Window, WindowBounds, WindowOptions, div,
3 prelude::*, px, rgb, size,
4};
5use gpui_platform::application;
6
7#[derive(Clone, Copy)]
8struct DragInfo {
9 ix: usize,
10 color: Hsla,
11 position: Point<Pixels>,
12}
13
14impl DragInfo {
15 fn new(ix: usize, color: Hsla) -> Self {
16 Self {
17 ix,
18 color,
19 position: Point::default(),
20 }
21 }
22
23 fn position(mut self, pos: Point<Pixels>) -> Self {
24 self.position = pos;
25 self
26 }
27}
28
29impl Render for DragInfo {
30 fn render(&mut self, _: &mut Window, _: &mut Context<'_, Self>) -> impl IntoElement {
31 let size = gpui::size(px(120.), px(50.));
32
33 div()
34 .pl(self.position.x - size.width.half())
35 .pt(self.position.y - size.height.half())
36 .child(
37 div()
38 .flex()
39 .justify_center()
40 .items_center()
41 .w(size.width)
42 .h(size.height)
43 .bg(self.color.opacity(0.5))
44 .text_color(gpui::white())
45 .text_xs()
46 .shadow_md()
47 .child(format!("Item {}", self.ix)),
48 )
49 }
50}
51
52struct DragDrop {
53 drop_on: Option<DragInfo>,
54}
55
56impl DragDrop {
57 fn new() -> Self {
58 Self { drop_on: None }
59 }
60}
61
62impl Render for DragDrop {
63 fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
64 let items = [gpui::blue(), gpui::red(), gpui::green()];
65
66 div()
67 .size_full()
68 .flex()
69 .flex_col()
70 .gap_5()
71 .bg(gpui::white())
72 .justify_center()
73 .items_center()
74 .text_color(rgb(0x333333))
75 .child(div().text_xl().text_center().child("Drop & Drop"))
76 .child(
77 div()
78 .w_full()
79 .mb_10()
80 .justify_center()
81 .flex()
82 .flex_row()
83 .gap_4()
84 .items_center()
85 .children(items.into_iter().enumerate().map(|(ix, color)| {
86 let drag_info = DragInfo::new(ix, color);
87
88 div()
89 .id(("item", ix))
90 .size_32()
91 .flex()
92 .justify_center()
93 .items_center()
94 .border_2()
95 .border_color(color)
96 .text_color(color)
97 .cursor_move()
98 .hover(|this| this.bg(color.opacity(0.2)))
99 .child(format!("Item ({})", ix))
100 .on_drag(drag_info, |info: &DragInfo, position, _, cx| {
101 cx.new(|_| info.position(position))
102 })
103 })),
104 )
105 .child(
106 div()
107 .id("drop-target")
108 .w_128()
109 .h_32()
110 .flex()
111 .justify_center()
112 .items_center()
113 .border_3()
114 .border_color(self.drop_on.map(|info| info.color).unwrap_or(gpui::black()))
115 .when_some(self.drop_on, |this, info| this.bg(info.color.opacity(0.5)))
116 .on_drop(cx.listener(|this, info: &DragInfo, _, _| {
117 this.drop_on = Some(*info);
118 }))
119 .child("Drop items here"),
120 )
121 }
122}
123
124fn main() {
125 application().run(|cx: &mut App| {
126 let bounds = Bounds::centered(None, size(px(800.), px(600.0)), cx);
127 cx.open_window(
128 WindowOptions {
129 window_bounds: Some(WindowBounds::Windowed(bounds)),
130 ..Default::default()
131 },
132 |_, cx| cx.new(|_| DragDrop::new()),
133 )
134 .unwrap();
135
136 cx.activate(true);
137 });
138}