Skip to content

Commit 7fad3a3

Browse files
committed
Re-add checkbox, combobox and pixmap functionality to iui
1 parent de605da commit 7fad3a3

File tree

8 files changed

+1087
-16
lines changed

8 files changed

+1087
-16
lines changed

iui/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,4 @@ maintenance = { status = "actively-developed" }
4646
bitflags = "0.7"
4747
libc = "0.2"
4848
failure = "0.1.1"
49-
ui-sys = "0.1.1"
49+
ui-sys = { version = "0.1.2", path = "../ui-sys" }

iui/src/controls/area.rs

Lines changed: 257 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
//! Provides a way to allocate an area in the window for custom drawing.
2+
3+
use controls::Control;
4+
use ui::UI;
5+
use draw;
6+
use libc::c_int;
7+
use std::mem;
8+
use ui_sys::{self, uiArea, uiAreaDrawParams, uiAreaHandler, uiAreaKeyEvent, uiAreaMouseEvent,
9+
uiControl};
10+
pub use ui_sys::uiExtKey as ExtKey;
11+
12+
pub trait AreaHandler {
13+
fn draw(&mut self, _area: &Area, _area_draw_params: &AreaDrawParams) {}
14+
fn mouse_event(&mut self, _area: &Area, _area_mouse_event: &AreaMouseEvent) {}
15+
fn mouse_crossed(&mut self, _area: &Area, _left: bool) {}
16+
fn drag_broken(&mut self, _area: &Area) {}
17+
fn key_event(&mut self, _area: &Area, _area_key_event: &AreaKeyEvent) -> bool {
18+
true
19+
}
20+
}
21+
22+
#[repr(C)]
23+
struct RustAreaHandler {
24+
ui_area_handler: uiAreaHandler,
25+
trait_object: Box<AreaHandler>,
26+
}
27+
28+
impl RustAreaHandler {
29+
fn new(_ctx: &UI, trait_object: Box<AreaHandler>) -> Box<RustAreaHandler> {
30+
return Box::new(RustAreaHandler {
31+
ui_area_handler: uiAreaHandler {
32+
Draw: draw,
33+
MouseEvent: mouse_event,
34+
MouseCrossed: mouse_crossed,
35+
DragBroken: drag_broken,
36+
KeyEvent: key_event,
37+
},
38+
trait_object: trait_object,
39+
});
40+
41+
extern "C" fn draw(
42+
ui_area_handler: *mut uiAreaHandler,
43+
ui_area: *mut uiArea,
44+
ui_area_draw_params: *mut uiAreaDrawParams,
45+
) {
46+
unsafe {
47+
let area = Area::from_ui_area(ui_area);
48+
let area_draw_params =
49+
AreaDrawParams::from_ui_area_draw_params(&*ui_area_draw_params);
50+
(*(ui_area_handler as *mut RustAreaHandler))
51+
.trait_object
52+
.draw(&area, &area_draw_params);
53+
mem::forget(area_draw_params);
54+
mem::forget(area);
55+
}
56+
}
57+
58+
extern "C" fn mouse_event(
59+
ui_area_handler: *mut uiAreaHandler,
60+
ui_area: *mut uiArea,
61+
ui_area_mouse_event: *mut uiAreaMouseEvent,
62+
) {
63+
unsafe {
64+
let area = Area::from_ui_area(ui_area);
65+
let area_mouse_event =
66+
AreaMouseEvent::from_ui_area_mouse_event(&*ui_area_mouse_event);
67+
(*(ui_area_handler as *mut RustAreaHandler))
68+
.trait_object
69+
.mouse_event(&area, &area_mouse_event);
70+
mem::forget(area_mouse_event);
71+
mem::forget(area);
72+
}
73+
}
74+
75+
extern "C" fn mouse_crossed(
76+
ui_area_handler: *mut uiAreaHandler,
77+
ui_area: *mut uiArea,
78+
left: c_int,
79+
) {
80+
unsafe {
81+
let area = Area::from_ui_area(ui_area);
82+
(*(ui_area_handler as *mut RustAreaHandler))
83+
.trait_object
84+
.mouse_crossed(&area, left != 0);
85+
mem::forget(area);
86+
}
87+
}
88+
89+
extern "C" fn drag_broken(ui_area_handler: *mut uiAreaHandler, ui_area: *mut uiArea) {
90+
unsafe {
91+
let area = Area::from_ui_area(ui_area);
92+
(*(ui_area_handler as *mut RustAreaHandler))
93+
.trait_object
94+
.drag_broken(&area);
95+
mem::forget(area);
96+
}
97+
}
98+
99+
extern "C" fn key_event(
100+
ui_area_handler: *mut uiAreaHandler,
101+
ui_area: *mut uiArea,
102+
ui_area_key_event: *mut uiAreaKeyEvent,
103+
) -> c_int {
104+
unsafe {
105+
let area = Area::from_ui_area(ui_area);
106+
let area_key_event = AreaKeyEvent::from_ui_area_key_event(&*ui_area_key_event);
107+
let result = (*(ui_area_handler as *mut RustAreaHandler))
108+
.trait_object
109+
.key_event(&area, &area_key_event);
110+
mem::forget(area_key_event);
111+
mem::forget(area);
112+
result as c_int
113+
}
114+
}
115+
}
116+
}
117+
118+
define_control!{
119+
/// A control which takes up space on which the application can draw custom content.
120+
rust_type: Area,
121+
sys_type: uiArea
122+
}
123+
124+
impl Area {
125+
pub fn new(ctx: &UI, area_handler: Box<AreaHandler>) -> Area {
126+
unsafe {
127+
let mut rust_area_handler = RustAreaHandler::new(ctx, area_handler);
128+
let area = Area::from_raw(ui_sys::uiNewArea(
129+
&mut *rust_area_handler as *mut RustAreaHandler as *mut uiAreaHandler,
130+
));
131+
mem::forget(rust_area_handler);
132+
area
133+
}
134+
}
135+
136+
pub fn new_scrolling(ctx: &UI, area_handler: Box<AreaHandler>, width: i64, height: i64) -> Area {
137+
unsafe {
138+
let mut rust_area_handler = RustAreaHandler::new(ctx, area_handler);
139+
let area = Area::from_raw(ui_sys::uiNewScrollingArea(
140+
&mut *rust_area_handler as *mut RustAreaHandler as *mut uiAreaHandler,
141+
width,
142+
height,
143+
));
144+
mem::forget(rust_area_handler);
145+
area
146+
}
147+
}
148+
149+
pub unsafe fn from_ui_area(ui_area: *mut uiArea) -> Area {
150+
Area { uiArea: ui_area }
151+
}
152+
153+
pub fn set_size(&self, _ctx: &UI, width: i64, height: i64) {
154+
unsafe { ui_sys::uiAreaSetSize(self.uiArea, width, height) }
155+
}
156+
157+
pub fn queue_redraw_all(&self, _ctx: &UI) {
158+
unsafe { ui_sys::uiAreaQueueRedrawAll(self.uiArea) }
159+
}
160+
161+
pub fn scroll_to(&self, _ctx: &UI, x: f64, y: f64, width: f64, height: f64) {
162+
unsafe { ui_sys::uiAreaScrollTo(self.uiArea, x, y, width, height) }
163+
}
164+
}
165+
166+
pub struct AreaDrawParams {
167+
pub context: draw::Context,
168+
169+
pub area_width: f64,
170+
pub area_height: f64,
171+
172+
pub clip_x: f64,
173+
pub clip_y: f64,
174+
pub clip_width: f64,
175+
pub clip_height: f64,
176+
}
177+
178+
impl AreaDrawParams {
179+
// TODO: check if UI is initialized?
180+
unsafe fn from_ui_area_draw_params(ui_area_draw_params: &uiAreaDrawParams) -> AreaDrawParams {
181+
AreaDrawParams {
182+
context: draw::Context::from_ui_draw_context(ui_area_draw_params.Context),
183+
area_width: ui_area_draw_params.AreaWidth,
184+
area_height: ui_area_draw_params.AreaHeight,
185+
clip_x: ui_area_draw_params.ClipX,
186+
clip_y: ui_area_draw_params.ClipY,
187+
clip_width: ui_area_draw_params.ClipWidth,
188+
clip_height: ui_area_draw_params.ClipHeight,
189+
}
190+
}
191+
}
192+
193+
bitflags! {
194+
pub flags Modifiers: u8 {
195+
const MODIFIER_CTRL = 1 << 0,
196+
const MODIFIER_ALT = 1 << 1,
197+
const MODIFIER_SHIFT = 1 << 2,
198+
const MODIFIER_SUPER = 1 << 3,
199+
}
200+
}
201+
202+
#[derive(Copy, Clone, Debug)]
203+
pub struct AreaMouseEvent {
204+
pub x: f64,
205+
pub y: f64,
206+
207+
pub area_width: f64,
208+
pub area_height: f64,
209+
210+
pub down: i32,
211+
pub up: i32,
212+
213+
pub count: i32,
214+
215+
pub modifiers: Modifiers,
216+
217+
pub held_1_to_64: u64,
218+
}
219+
220+
impl AreaMouseEvent {
221+
// TODO: check if UI is initialized?
222+
pub fn from_ui_area_mouse_event(ui_area_mouse_event: &uiAreaMouseEvent) -> AreaMouseEvent {
223+
AreaMouseEvent {
224+
x: ui_area_mouse_event.X,
225+
y: ui_area_mouse_event.Y,
226+
area_width: ui_area_mouse_event.AreaWidth,
227+
area_height: ui_area_mouse_event.AreaHeight,
228+
down: ui_area_mouse_event.Down,
229+
up: ui_area_mouse_event.Up,
230+
count: ui_area_mouse_event.Count,
231+
modifiers: Modifiers::from_bits(ui_area_mouse_event.Modifiers as u8).unwrap(),
232+
held_1_to_64: ui_area_mouse_event.Held1To64,
233+
}
234+
}
235+
}
236+
237+
#[derive(Copy, Clone, Debug)]
238+
pub struct AreaKeyEvent {
239+
pub key: u8,
240+
pub ext_key: ExtKey,
241+
pub modifier: Modifiers,
242+
pub modifiers: Modifiers,
243+
pub up: bool,
244+
}
245+
246+
impl AreaKeyEvent {
247+
// TODO: check if UI is initialized?
248+
pub fn from_ui_area_key_event(ui_area_key_event: &uiAreaKeyEvent) -> AreaKeyEvent {
249+
AreaKeyEvent {
250+
key: ui_area_key_event.Key as u8,
251+
ext_key: ui_area_key_event.ExtKey,
252+
modifier: Modifiers::from_bits(ui_area_key_event.Modifier as u8).unwrap(),
253+
modifiers: Modifiers::from_bits(ui_area_key_event.Modifiers as u8).unwrap(),
254+
up: ui_area_key_event.Up != 0,
255+
}
256+
}
257+
}

iui/src/controls/entry.rs

Lines changed: 92 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use std::mem;
44
use std::ffi::{CStr, CString};
55
use std::i64;
66
use libc::c_void;
7-
use ui_sys::{self, uiControl, uiSpinbox, uiSlider, uiEntry, uiMultilineEntry};
7+
use ui_sys::{self, uiControl, uiSpinbox, uiSlider, uiEntry, uiMultilineEntry, uiCombobox,
8+
uiCheckbox};
89
use super::Control;
910
use ui::UI;
1011

@@ -22,13 +23,13 @@ pub trait TextEntry {
2223

2324
define_control!{
2425
/// Numerical entry control which allows users to set any value in a range by typing or incrementing/decrementing.
25-
rust_type: Spinbox,
26+
rust_type: Spinbox,
2627
sys_type: uiSpinbox
2728
}
2829

29-
define_control!{
30+
define_control!{
3031
/// Numerical entry which allows users to select a value by picking a location along a line.
31-
rust_type: Slider,
32+
rust_type: Slider,
3233
sys_type: uiSlider
3334
}
3435

@@ -192,3 +193,90 @@ impl TextEntry for MultilineEntry {
192193
}
193194
}
194195
}
196+
197+
define_control! {
198+
/// A control which allows the user to select any one of its options, from a list shown only when selected.
199+
rust_type: Combobox,
200+
sys_type: uiCombobox
201+
}
202+
203+
impl Combobox {
204+
/// Create a new Combobox
205+
pub fn new(_ctx: &UI) -> Self {
206+
unsafe { Combobox::from_raw(ui_sys::uiNewCombobox()) }
207+
}
208+
209+
/// Adds a new option to the combination box.
210+
pub fn append(&self, _ctx: &UI, name: &str) {
211+
unsafe {
212+
let c_string = CString::new(name.as_bytes().to_vec()).unwrap();
213+
ui_sys::uiComboboxAppend(self.uiCombobox, c_string.as_ptr())
214+
}
215+
}
216+
217+
pub fn set_selected(&mut self, _ctx: &UI, value: i64) {
218+
unsafe { ui_sys::uiComboboxSetSelected(self.uiCombobox, value) }
219+
}
220+
221+
pub fn on_selected<F: FnMut(i64)>(&mut self, _ctx: &UI, callback: F) {
222+
unsafe {
223+
let mut data: Box<Box<FnMut(i64)>> = Box::new(Box::new(callback));
224+
ui_sys::uiComboboxOnSelected(
225+
self.uiCombobox,
226+
c_callback,
227+
&mut *data as *mut Box<FnMut(i64)> as *mut c_void,
228+
);
229+
mem::forget(data);
230+
}
231+
232+
extern "C" fn c_callback(combobox: *mut uiCombobox, data: *mut c_void) {
233+
unsafe {
234+
let val = ui_sys::uiComboboxSelected(combobox);
235+
// let combobox = Combobox::from_ui_control(combobox);
236+
mem::transmute::<*mut c_void, &mut Box<FnMut(i64)>>(data)(val);
237+
// mem::forget(combobox);
238+
}
239+
}
240+
}
241+
}
242+
243+
define_control! {
244+
/// A control which allows the user to select any one of its options, from a list shown only when selected.
245+
rust_type: Checkbox,
246+
sys_type: uiCheckbox
247+
}
248+
249+
impl Checkbox {
250+
// Create a new Checkbox which can produce values from `min` to `max`.
251+
pub fn new(_ctx: &UI, text: &str) -> Self {
252+
let c_string = CString::new(text.as_bytes().to_vec()).unwrap();
253+
unsafe { Checkbox::from_raw(ui_sys::uiNewCheckbox(c_string.as_ptr())) }
254+
}
255+
256+
pub fn checked(&self, _ctx: &UI) -> bool {
257+
unsafe { ui_sys::uiCheckboxChecked(self.uiCheckbox) != 0 }
258+
}
259+
260+
pub fn set_checked(&mut self, _ctx: &UI, checked: bool) {
261+
unsafe { ui_sys::uiCheckboxSetChecked(self.uiCheckbox, checked as i32) }
262+
}
263+
264+
pub fn on_toggled<F: FnMut(bool)>(&mut self, _ctx: &UI, callback: F) {
265+
unsafe {
266+
let mut data: Box<Box<FnMut(bool)>> = Box::new(Box::new(callback));
267+
ui_sys::uiCheckboxOnToggled(
268+
self.uiCheckbox,
269+
c_callback,
270+
&mut *data as *mut Box<FnMut(bool)> as *mut c_void,
271+
);
272+
mem::forget(data);
273+
}
274+
275+
extern "C" fn c_callback(checkbox: *mut uiCheckbox, data: *mut c_void) {
276+
unsafe {
277+
let val = ui_sys::uiCheckboxChecked(checkbox) != 0;
278+
mem::transmute::<*mut c_void, &mut Box<FnMut(bool)>>(data)(val);
279+
}
280+
}
281+
}
282+
}

0 commit comments

Comments
 (0)