diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c3c091a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +ui-sys/target +ui-sys/Cargo.lock +ui/target +ui/Cargo.lock diff --git a/ui-sys/Cargo.toml b/ui-sys/Cargo.toml index 4683485d..2ccde7d2 100644 --- a/ui-sys/Cargo.toml +++ b/ui-sys/Cargo.toml @@ -10,5 +10,4 @@ description = "Native bindings to the minimalist, cross-platform, widget set `li libc = "0.2" [build-dependencies] -make-cmd = "0.1" - +cmake = "0.1.17" diff --git a/ui-sys/build.rs b/ui-sys/build.rs index bebe630e..e0af70bc 100644 --- a/ui-sys/build.rs +++ b/ui-sys/build.rs @@ -1,22 +1,34 @@ -extern crate make_cmd; +extern crate cmake; -use std::env; +use std::env::var; +use std::fs::rename; use std::path::Path; use std::process::Command; fn main() { + println!("cargo:rerun-if-changed=libui"); + if !Path::new("libui/.git").exists() { - Command::new("git").args(&["submodule", "update", "--init"]).status().unwrap(); + Command::new("git") + .args(&["submodule", "update", "--init"]) + .status() + .expect("initializing submodule libui"); } - let out_dir = env::var("OUT_DIR").unwrap(); - let outdir_argument = format!("OUTDIR={}", out_dir); - let objdir_argument = format!("OBJDIR={}/obj", out_dir); - make_cmd::gnu_make().args(&["-C", "libui", &*outdir_argument, &*objdir_argument]) - .status() - .unwrap(); + let profile = var("PROFILE").expect("reading environment variable PROFILE"); + let dst = cmake::Config::new("libui") + .profile(profile.as_str()) + .build_target("") + .build(); + + let mut out_dir = dst.join(Path::new("build/out")); + let target = var("TARGET").expect("reading environment variable TARGET"); + if target.contains("msvc") { + out_dir = out_dir.join(Path::new(profile.as_str())); + rename(out_dir.join("libui.lib"), out_dir.join("ui.lib")).expect("renaming file libui.lib"); + } + + println!("cargo:rustc-link-search={}", out_dir.display()); println!("cargo:rustc-link-lib=dylib=ui"); - println!("cargo:rustc-link-search=native={}", out_dir); } - diff --git a/ui-sys/libui b/ui-sys/libui index 156c3584..86c44855 160000 --- a/ui-sys/libui +++ b/ui-sys/libui @@ -1 +1 @@ -Subproject commit 156c3584f706753e892be77338d1b9c2cb669c5b +Subproject commit 86c4485578d6d58aff6528b27558bc1ccc6aadbe diff --git a/ui-sys/src/ffi.rs b/ui-sys/src/ffi.rs index fb5eee2f..be69f435 100644 --- a/ui-sys/src/ffi.rs +++ b/ui-sys/src/ffi.rs @@ -733,4 +733,3 @@ extern { data: *mut c_void); pub fn uiNewColorButton() -> *mut uiColorButton; } - diff --git a/ui-sys/src/lib.rs b/ui-sys/src/lib.rs index b0a99300..a47d82d0 100644 --- a/ui-sys/src/lib.rs +++ b/ui-sys/src/lib.rs @@ -4,7 +4,7 @@ extern crate libc; -use libc::{c_char, c_double, c_int, c_void, intmax_t, size_t, uintmax_t}; +use libc::{c_char, c_double, c_int, c_void, size_t}; pub mod platform { pub mod macos; @@ -25,6 +25,8 @@ extern { pub fn uiFreeInitError(err: *const c_char); pub fn uiMain(); + pub fn uiMainSteps(); + pub fn uiMainStep(wait: c_int) -> c_int; pub fn uiQuit(); pub fn uiQueueMain(f: extern "C" fn(data: *mut c_void), data: *mut c_void); @@ -71,9 +73,10 @@ extern { -> *mut uiControl; pub fn uiFreeControl(control: *mut uiControl); - pub fn uiControlVerifyDestroy(control: *mut uiControl); pub fn uiControlVerifySetParent(control: *mut uiControl, new_parent: *mut uiControl); pub fn uiControlEnabledToUser(control: *mut uiControl) -> c_int; + + pub fn uiUserBugCannotSetParentOnToplevel(typ: *const c_char); } pub enum uiWindow {} @@ -82,9 +85,24 @@ pub enum uiWindow {} extern { pub fn uiWindowTitle(w: *mut uiWindow) -> *mut c_char; pub fn uiWindowSetTitle(w: *mut uiWindow, title: *const c_char); + pub fn uiWindowPosition(w: *mut uiWindow, x: *mut c_int, y: *mut c_int); + pub fn uiWindowSetPosition(w: *mut uiWindow, x: c_int, y: c_int); + pub fn uiWindowCenter(w: *mut uiWindow); + pub fn uiWindowOnPositionChanged(w: *mut uiWindow, + f: extern "C" fn(w: *mut uiWindow, data: *mut c_void), + data: *mut c_void); + pub fn uiWindowContentSize(w: *mut uiWindow, width: *mut c_int, height: *mut c_int); + pub fn uiWindowSetContentSize(w: *mut uiWindow, width: c_int, height: c_int); + pub fn uiWindowFullscreen(w: *mut uiWindow) -> c_int; + pub fn uiWindowSetFullscreen(w: *mut uiWindow, fullscreen: c_int); + pub fn uiWindowOnContentSizeChanged(w: *mut uiWindow, + f: extern "C" fn(w: *mut uiWindow, data: *mut c_void), + data: *mut c_void); pub fn uiWindowOnClosing(w: *mut uiWindow, f: extern "C" fn(w: *mut uiWindow, data: *mut c_void) -> c_int, data: *mut c_void); + pub fn uiWindowBorderless(w: *mut uiWindow) -> c_int; + pub fn uiWindowSetBorderless(w: *mut uiWindow, fullscreen: c_int); pub fn uiWindowSetChild(w: *mut uiWindow, child: *mut uiControl); pub fn uiWindowMargined(w: *mut uiWindow) -> c_int; pub fn uiWindowSetMargined(w: *mut uiWindow, margined: c_int); @@ -109,7 +127,7 @@ pub enum uiBox {} #[link(name = "ui")] extern { pub fn uiBoxAppend(b: *mut uiBox, child: *mut uiControl, stretchy: c_int); - pub fn uiBoxDelete(b: *mut uiBox, index: uintmax_t); + pub fn uiBoxDelete(b: *mut uiBox, index: c_int); pub fn uiBoxPadded(b: *mut uiBox) -> c_int; pub fn uiBoxSetPadded(b: *mut uiBox, padded: c_int); pub fn uiNewHorizontalBox() -> *mut uiBox; @@ -128,6 +146,8 @@ extern { pub fn uiEntryReadOnly(e: *mut uiEntry) -> c_int; pub fn uiEntrySetReadOnly(e: *mut uiEntry, readonly: c_int); pub fn uiNewEntry() -> *mut uiEntry; + pub fn uiNewPasswordEntry() -> *mut uiEntry; + pub fn uiNewSearchEntry() -> *mut uiEntry; } pub enum uiCheckbox {} @@ -158,11 +178,11 @@ pub enum uiTab {} #[link(name = "ui")] extern { pub fn uiTabAppend(t: *mut uiTab, name: *const c_char, c: *mut uiControl); - pub fn uiTabInsertAt(t: *mut uiTab, name: *const c_char, before: uintmax_t, c: *mut uiControl); - pub fn uiTabDelete(t: *mut uiTab, index: uintmax_t); - pub fn uiTabNumPages(t: *mut uiTab) -> uintmax_t; - pub fn uiTabMargined(t: *mut uiTab, page: uintmax_t) -> c_int; - pub fn uiTabSetMargined(t: *mut uiTab, page: uintmax_t, margined: c_int); + pub fn uiTabInsertAt(t: *mut uiTab, name: *const c_char, before: c_int, c: *mut uiControl); + pub fn uiTabDelete(t: *mut uiTab, index: c_int); + pub fn uiTabNumPages(t: *mut uiTab) -> c_int; + pub fn uiTabMargined(t: *mut uiTab, page: c_int) -> c_int; + pub fn uiTabSetMargined(t: *mut uiTab, page: c_int, margined: c_int); pub fn uiNewTab() -> *mut uiTab; } @@ -182,18 +202,19 @@ pub enum uiSpinbox {} #[link(name = "ui")] extern { - pub fn uiSpinboxValue(s: *mut uiSpinbox) -> intmax_t; - pub fn uiSpinboxSetValue(s: *mut uiSpinbox, value: intmax_t); + pub fn uiSpinboxValue(s: *mut uiSpinbox) -> c_int; + pub fn uiSpinboxSetValue(s: *mut uiSpinbox, value: c_int); pub fn uiSpinboxOnChanged(s: *mut uiSpinbox, f: extern "C" fn(s: *mut uiSpinbox, data: *mut c_void), data: *mut c_void); - pub fn uiNewSpinbox(min: intmax_t, max: intmax_t) -> *mut uiSpinbox; + pub fn uiNewSpinbox(min: c_int, max: c_int) -> *mut uiSpinbox; } pub enum uiProgressBar {} #[link(name = "ui")] extern { + pub fn uiProgressBarValue(p: *mut uiProgressBar) -> c_int; pub fn uiProgressBarSetValue(p: *mut uiProgressBar, n: c_int); pub fn uiNewProgressBar() -> *mut uiProgressBar; } @@ -202,12 +223,12 @@ pub enum uiSlider {} #[link(name = "ui")] extern { - pub fn uiSliderValue(s: *mut uiSlider) -> intmax_t; - pub fn uiSliderSetValue(s: *mut uiSlider, value: intmax_t); + pub fn uiSliderValue(s: *mut uiSlider) -> c_int; + pub fn uiSliderSetValue(s: *mut uiSlider, value: c_int); pub fn uiSliderOnChanged(s: *mut uiSlider, f: extern "C" fn(s: *mut uiSlider, data: *mut c_void), data: *mut c_void); - pub fn uiNewSlider(min: intmax_t, max: intmax_t) -> *mut uiSlider; + pub fn uiNewSlider(min: c_int, max: c_int) -> *mut uiSlider; } pub enum uiSeparator {} @@ -215,6 +236,7 @@ pub enum uiSeparator {} #[link(name = "ui")] extern { pub fn uiNewHorizontalSeparator() -> *mut uiSeparator; + pub fn uiNewVerticalSeparator() -> *mut uiSeparator; } pub enum uiCombobox {} @@ -222,13 +244,25 @@ pub enum uiCombobox {} #[link(name = "ui")] extern { pub fn uiComboboxAppend(c: *mut uiCombobox, text: *const c_char); - pub fn uiComboboxSelected(c: *mut uiCombobox) -> intmax_t; - pub fn uiComboboxSetSelected(c: *mut uiCombobox, n: intmax_t); + pub fn uiComboboxSelected(c: *mut uiCombobox) -> c_int; + pub fn uiComboboxSetSelected(c: *mut uiCombobox, n: c_int); pub fn uiComboboxOnSelected(c: *mut uiCombobox, f: extern "C" fn(c: *mut uiCombobox, data: *mut c_void), data: *mut c_void); pub fn uiNewCombobox() -> *mut uiCombobox; - pub fn uiNewEditableCombobox() -> *mut uiCombobox; +} + +pub enum uiEditableCombobox {} + +#[link(name = "ui")] +extern { + pub fn uiEditableComboboxAppend(c: *mut uiEditableCombobox, text: *const c_char); + pub fn uiEditableComboboxText(c: *mut uiEditableCombobox) -> *mut c_char; + pub fn uiEditableComboboxSetText(c: *mut uiEditableCombobox, text: *const c_char); + pub fn uiEditableComboboxOnChanged(c: *mut uiEditableCombobox, + f: extern "C" fn(c: *mut uiEditableCombobox, data: *mut c_void), + data: *mut c_void); + pub fn uiNewEditableCombobox() -> *mut uiEditableCombobox; } pub enum uiRadioButtons {} @@ -236,6 +270,11 @@ pub enum uiRadioButtons {} #[link(name = "ui")] extern { pub fn uiRadioButtonsAppend(r: *mut uiRadioButtons, text: *const c_char); + pub fn uiRadioButtonsSelected(r: *mut uiRadioButtons) -> c_int; + pub fn uiRadioButtonsSetSelected(r: *mut uiRadioButtons, value: c_int); + pub fn uiRadioButtonsOnSelected(r: *mut uiRadioButtons, + f: extern "C" fn(r: *mut uiRadioButtons, data: *mut c_void), + data: *mut c_void); pub fn uiNewRadioButtons() -> *mut uiRadioButtons; } @@ -261,6 +300,7 @@ extern { pub fn uiMultilineEntryReadOnly(e: *mut uiMultilineEntry) -> c_int; pub fn uiMultilineEntrySetReadOnly(e: *mut uiMultilineEntry, readonly: c_int); pub fn uiNewMultilineEntry() -> *mut uiMultilineEntry; + pub fn uiNewNonWrappingMultilineEntry() -> *mut uiMultilineEntry; } pub enum uiMenuItem {} @@ -321,7 +361,7 @@ pub struct uiAreaHandler { #[link(name = "ui")] extern { - pub fn uiAreaSetSize(a: *mut uiArea, width: intmax_t, height: intmax_t); + pub fn uiAreaSetSize(a: *mut uiArea, width: c_int, height: c_int); pub fn uiAreaQueueRedrawAll(a: *mut uiArea); pub fn uiAreaScrollTo(a: *mut uiArea, x: c_double, @@ -329,7 +369,7 @@ extern { width: c_double, height: c_double); pub fn uiNewArea(ah: *mut uiAreaHandler) -> *mut uiArea; - pub fn uiNewScrollingArea(ah: *mut uiAreaHandler, width: intmax_t, height: intmax_t) + pub fn uiNewScrollingArea(ah: *mut uiAreaHandler, width: c_int, height: c_int) -> *mut uiArea; } @@ -523,8 +563,8 @@ pub enum uiDrawFontFamilies {} extern "C" { pub fn uiDrawListFontFamilies() -> *mut uiDrawFontFamilies; - pub fn uiDrawFontFamiliesNumFamilies(ff: *mut uiDrawFontFamilies) -> uintmax_t; - pub fn uiDrawFontFamiliesFamily(ff: *mut uiDrawFontFamilies, n: uintmax_t) -> *mut c_char; + pub fn uiDrawFontFamiliesNumFamilies(ff: *mut uiDrawFontFamilies) -> c_int; + pub fn uiDrawFontFamiliesFamily(ff: *mut uiDrawFontFamilies, n: c_int) -> *mut c_char; pub fn uiDrawFreeFontFamilies(ff: *mut uiDrawFontFamilies); } @@ -612,8 +652,8 @@ extern "C" { height: *mut c_double); pub fn uiDrawTextLayoutSetColor(layout: *mut uiDrawTextLayout, - startChar: intmax_t, - endChar: intmax_t, + startChar: c_int, + endChar: c_int, r: c_double, g: c_double, b: c_double, @@ -641,10 +681,10 @@ pub struct uiAreaMouseEvent { pub AreaWidth: c_double, pub AreaHeight: c_double, - pub Down: uintmax_t, - pub Up: uintmax_t, + pub Down: c_int, + pub Up: c_int, - pub Count: uintmax_t, + pub Count: c_int, pub Modifiers: uiModifiers, @@ -741,4 +781,3 @@ extern { data: *mut c_void); pub fn uiNewColorButton() -> *mut uiColorButton; } - diff --git a/ui/examples/controlgallery.rs b/ui/examples/controlgallery.rs index aaa43647..50fade90 100644 --- a/ui/examples/controlgallery.rs +++ b/ui/examples/controlgallery.rs @@ -2,7 +2,8 @@ extern crate ui; -use ui::{BoxControl, Button, Checkbox, ColorButton, Combobox, DateTimePicker, Entry}; +use ui::{BoxControl, Button, Checkbox, ColorButton, Combobox, EditableCombobox, + DateTimePicker, Entry}; use ui::{FontButton, Group, InitOptions, Label, Menu, MenuItem, ProgressBar, RadioButtons}; use ui::{Separator, Slider, Spinbox, Tab, Window}; @@ -97,7 +98,7 @@ fn run() { cbox.append("Combobox Item 3"); inner.append(cbox.into(), false); - let cbox = Combobox::new_editable(); + let cbox = EditableCombobox::new(); cbox.append("Editable Item 1"); cbox.append("Editable Item 2"); cbox.append("Editable Item 3"); @@ -133,7 +134,7 @@ fn open_clicked(_: &MenuItem, mainwin: &Window) { } fn save_clicked(_: &MenuItem, mainwin: &Window) { - match ui::open_file(mainwin) { + match ui::save_file(mainwin) { Some(filename) => { ui::msg_box(mainwin, "File selected (don't worry, it's still there)", &*filename) } @@ -141,7 +142,6 @@ fn save_clicked(_: &MenuItem, mainwin: &Window) { } } -fn update(_: i64) { +fn update(_: i32) { // TODO(pcwalton) } - diff --git a/ui/src/controls.rs b/ui/src/controls.rs index 56992763..3e2306cf 100644 --- a/ui/src/controls.rs +++ b/ui/src/controls.rs @@ -7,7 +7,8 @@ use std::ffi::CString; use std::mem; use std::ptr; use ui_sys::{self, uiArea, uiAreaDrawParams, uiAreaHandler, uiAreaKeyEvent, uiAreaMouseEvent}; -use ui_sys::{uiBox, uiButton, uiCheckbox, uiColorButton, uiCombobox, uiControl, uiDateTimePicker}; +use ui_sys::{uiBox, uiButton, uiCheckbox, uiColorButton, uiCombobox, uiEditableCombobox, + uiControl, uiDateTimePicker}; use ui_sys::{uiEntry, uiFontButton, uiGroup, uiLabel, uiMultilineEntry, uiProgressBar}; use ui_sys::{uiRadioButtons, uiSeparator, uiSlider, uiSpinbox, uiTab}; @@ -273,7 +274,7 @@ impl BoxControl { /// to decrement its reference count per `libui`'s UI as of today, unless we maintain a /// separate list of children ourselves… #[inline] - pub fn delete(&self, index: u64) { + pub fn delete(&self, index: i32) { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiBoxDelete(self.ui_box, index) @@ -376,6 +377,22 @@ impl Entry { Entry::from_ui_control(ui_sys::uiNewEntry()) } } + + #[inline] + pub fn new_password() -> Entry { + ffi_utils::ensure_initialized(); + unsafe { + Entry::from_ui_control(ui_sys::uiNewPasswordEntry()) + } + } + + #[inline] + pub fn new_search() -> Entry { + ffi_utils::ensure_initialized(); + unsafe { + Entry::from_ui_control(ui_sys::uiNewSearchEntry()) + } + } } define_control!(Checkbox, uiCheckbox, ui_checkbox); @@ -487,7 +504,7 @@ impl Tab { } #[inline] - pub fn insert_at(&self, name: &str, before: u64, control: Control) { + pub fn insert_at(&self, name: &str, before: i32, control: Control) { ffi_utils::ensure_initialized(); unsafe { let c_string = CString::new(name.as_bytes().to_vec()).unwrap(); @@ -499,7 +516,7 @@ impl Tab { /// to decrement its reference count per `libui`'s UI as of today, unless we maintain a /// separate list of children ourselves… #[inline] - pub fn delete(&self, index: u64) { + pub fn delete(&self, index: i32) { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiTabDelete(self.ui_tab, index) @@ -507,7 +524,7 @@ impl Tab { } #[inline] - pub fn margined(&self, page: u64) -> bool { + pub fn margined(&self, page: i32) -> bool { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiTabMargined(self.ui_tab, page) != 0 @@ -515,7 +532,7 @@ impl Tab { } #[inline] - pub fn set_margined(&self, page: u64, margined: bool) { + pub fn set_margined(&self, page: i32, margined: bool) { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiTabSetMargined(self.ui_tab, page, margined as c_int) @@ -589,7 +606,7 @@ define_control!(Spinbox, uiSpinbox, ui_spinbox); impl Spinbox { #[inline] - pub fn value(&self) -> i64 { + pub fn value(&self) -> i32 { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiSpinboxValue(self.ui_spinbox) @@ -597,7 +614,7 @@ impl Spinbox { } #[inline] - pub fn set_value(&self, value: i64) { + pub fn set_value(&self, value: i32) { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiSpinboxSetValue(self.ui_spinbox, value) @@ -625,7 +642,7 @@ impl Spinbox { } #[inline] - pub fn new(min: i64, max: i64) -> Spinbox { + pub fn new(min: i32, max: i32) -> Spinbox { ffi_utils::ensure_initialized(); unsafe { Spinbox::from_ui_control(ui_sys::uiNewSpinbox(min, max)) @@ -636,6 +653,14 @@ impl Spinbox { define_control!(ProgressBar, uiProgressBar, ui_progress_bar); impl ProgressBar { + #[inline] + pub fn value(&self) -> i32 { + ffi_utils::ensure_initialized(); + unsafe { + ui_sys::uiProgressBarValue(self.ui_progress_bar) + } + } + #[inline] pub fn set_value(&self, n: i32) { ffi_utils::ensure_initialized(); @@ -657,7 +682,7 @@ define_control!(Slider, uiSlider, ui_slider); impl Slider { #[inline] - pub fn value(&self) -> i64 { + pub fn value(&self) -> i32 { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiSliderValue(self.ui_slider) @@ -665,7 +690,7 @@ impl Slider { } #[inline] - pub fn set_value(&self, value: i64) { + pub fn set_value(&self, value: i32) { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiSliderSetValue(self.ui_slider, value) @@ -693,7 +718,7 @@ impl Slider { } #[inline] - pub fn new(min: i64, max: i64) -> Slider { + pub fn new(min: i32, max: i32) -> Slider { ffi_utils::ensure_initialized(); unsafe { Slider::from_ui_control(ui_sys::uiNewSlider(min, max)) @@ -711,6 +736,14 @@ impl Separator { Separator::from_ui_control(ui_sys::uiNewHorizontalSeparator()) } } + + #[inline] + pub fn new_vertical() -> Separator { + ffi_utils::ensure_initialized(); + unsafe { + Separator::from_ui_control(ui_sys::uiNewVerticalSeparator()) + } + } } define_control!(Combobox, uiCombobox, ui_combobox); @@ -726,7 +759,7 @@ impl Combobox { } #[inline] - pub fn selected(&self) -> i64 { + pub fn selected(&self) -> i32 { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiComboboxSelected(self.ui_combobox) @@ -734,7 +767,7 @@ impl Combobox { } #[inline] - pub fn set_selected(&self, n: i64) { + pub fn set_selected(&self, n: i32) { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiComboboxSetSelected(self.ui_combobox, n) @@ -768,18 +801,67 @@ impl Combobox { Combobox::from_ui_control(ui_sys::uiNewCombobox()) } } +} + +define_control!(EditableCombobox, uiEditableCombobox, ui_editable_combobox); + +impl EditableCombobox { + #[inline] + pub fn append(&self, name: &str) { + ffi_utils::ensure_initialized(); + unsafe { + let c_string = CString::new(name.as_bytes().to_vec()).unwrap(); + ui_sys::uiEditableComboboxAppend(self.ui_editable_combobox, c_string.as_ptr()) + } + } + + #[inline] + pub fn text(&self) -> Text { + ffi_utils::ensure_initialized(); + unsafe { + Text::new(ui_sys::uiEditableComboboxText(self.ui_editable_combobox)) + } + } + + #[inline] + pub fn set_text(&self, text: &str) { + ffi_utils::ensure_initialized(); + let c_string = CString::new(text.as_bytes().to_vec()).unwrap(); + unsafe { + ui_sys::uiEditableComboboxSetText(self.ui_editable_combobox, c_string.as_ptr()) + } + } #[inline] - pub fn new_editable() -> Combobox { + pub fn on_changed(&self, callback: Box) { ffi_utils::ensure_initialized(); unsafe { - Combobox::from_ui_control(ui_sys::uiNewEditableCombobox()) + let mut data: Box> = Box::new(callback); + ui_sys::uiEditableComboboxOnChanged(self.ui_editable_combobox, + c_callback, + &mut *data as *mut Box as *mut c_void); + mem::forget(data); + } + + extern "C" fn c_callback(editablecombobox: *mut uiEditableCombobox, data: *mut c_void) { + unsafe { + let editablecombobox = EditableCombobox::from_ui_control(editablecombobox); + mem::transmute::<*mut c_void, + &mut Box>(data)(&editablecombobox); + mem::forget(editablecombobox); + } + } + } + + #[inline] + pub fn new() -> EditableCombobox { + ffi_utils::ensure_initialized(); + unsafe { + EditableCombobox::from_ui_control(ui_sys::uiNewEditableCombobox()) } } } -// FIXME(pcwalton): Are these supposed to be a subclass of something? They don't seem very usable -// with just the `uiRadioButtons*` methods… define_control!(RadioButtons, uiRadioButtons, ui_radio_buttons); impl RadioButtons { @@ -792,6 +874,43 @@ impl RadioButtons { } } + #[inline] + pub fn selected(&self) -> i32 { + ffi_utils::ensure_initialized(); + unsafe { + ui_sys::uiRadioButtonsSelected(self.ui_radio_buttons) + } + } + + #[inline] + pub fn set_selected(&self, n: i32) { + ffi_utils::ensure_initialized(); + unsafe { + ui_sys::uiRadioButtonsSetSelected(self.ui_radio_buttons, n) + } + } + + #[inline] + pub fn on_selected(&self, callback: Box) { + ffi_utils::ensure_initialized(); + unsafe { + let mut data: Box> = Box::new(callback); + ui_sys::uiRadioButtonsOnSelected(self.ui_radio_buttons, + c_callback, + &mut *data as *mut Box as + *mut c_void); + mem::forget(data); + } + + extern "C" fn c_callback(ui_font_button: *mut uiRadioButtons, data: *mut c_void) { + unsafe { + let radio_buttons = RadioButtons::from_ui_control(ui_font_button); + mem::transmute::<*mut c_void, &mut Box>(data)(&radio_buttons); + mem::forget(radio_buttons); + } + } + } + #[inline] pub fn new() -> RadioButtons { ffi_utils::ensure_initialized(); @@ -893,6 +1012,14 @@ impl MultilineEntry { MultilineEntry::from_ui_control(ui_sys::uiNewMultilineEntry()) } } + + #[inline] + pub fn new_non_wrapping() -> MultilineEntry { + ffi_utils::ensure_initialized(); + unsafe { + MultilineEntry::from_ui_control(ui_sys::uiNewNonWrappingMultilineEntry()) + } + } } pub trait AreaHandler { @@ -1002,7 +1129,7 @@ impl Area { } #[inline] - pub fn set_size(&self, width: i64, height: i64) { + pub fn set_size(&self, width: i32, height: i32) { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiAreaSetSize(self.ui_area, width, height) @@ -1040,7 +1167,7 @@ impl Area { } #[inline] - pub fn new_scrolling(area_handler: Box, width: i64, height: i64) -> Area { + pub fn new_scrolling(area_handler: Box, width: i32, height: i32) -> Area { ffi_utils::ensure_initialized(); unsafe { let mut rust_area_handler = RustAreaHandler::new(area_handler); @@ -1101,10 +1228,10 @@ pub struct AreaMouseEvent { pub area_width: f64, pub area_height: f64, - pub down: u64, - pub up: u64, + pub down: i32, + pub up: i32, - pub count: u64, + pub count: i32, pub modifiers: Modifiers, @@ -1256,4 +1383,3 @@ pub struct Color { b: f64, a: f64, } - diff --git a/ui/src/draw.rs b/ui/src/draw.rs index 61857a4c..6f98b935 100644 --- a/ui/src/draw.rs +++ b/ui/src/draw.rs @@ -501,7 +501,7 @@ impl FontFamilies { } #[inline] - pub fn len(&self) -> u64 { + pub fn len(&self) -> i32 { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiDrawFontFamiliesNumFamilies(self.ui_draw_font_families) @@ -509,7 +509,7 @@ impl FontFamilies { } #[inline] - pub fn family(&self, index: u64) -> Text { + pub fn family(&self, index: i32) -> Text { ffi_utils::ensure_initialized(); assert!(index < self.len()); unsafe { @@ -693,7 +693,7 @@ pub mod text { } #[inline] - pub fn set_color(&self, start_char: i64, end_char: i64, r: f64, g: f64, b: f64, a: f64) { + pub fn set_color(&self, start_char: i32, end_char: i32, r: f64, g: f64, b: f64, a: f64) { ffi_utils::ensure_initialized(); unsafe { ui_sys::uiDrawTextLayoutSetColor(self.ui_draw_text_layout, @@ -707,4 +707,3 @@ pub mod text { } } } - diff --git a/ui/src/lib.rs b/ui/src/lib.rs index e8891f1f..5ebae4f1 100644 --- a/ui/src/lib.rs +++ b/ui/src/lib.rs @@ -10,11 +10,13 @@ extern crate libc; extern crate ui_sys; pub use controls::{Area, AreaDrawParams, AreaHandler, BoxControl, Button, Checkbox, ColorButton}; -pub use controls::{Combobox, Control, DateTimePicker, Entry, FontButton, Group, Label}; +pub use controls::{Combobox, EditableCombobox, Control, DateTimePicker, Entry, FontButton, Group, + Label}; pub use controls::{MultilineEntry, ProgressBar, RadioButtons, Separator, Slider, Spinbox, Tab}; pub use ffi_utils::Text; pub use menus::{Menu, MenuItem}; -pub use ui::{InitError, InitOptions, init, main, msg_box, msg_box_error, on_should_quit}; +pub use ui::{InitError, InitOptions, init, main, main_steps, main_step, msg_box, msg_box_error, + on_should_quit}; pub use ui::{open_file, queue_main, quit, save_file, uninit}; pub use windows::Window; @@ -25,4 +27,3 @@ pub mod ffi_utils; mod menus; mod ui; mod windows; - diff --git a/ui/src/ui.rs b/ui/src/ui.rs index ccdc4dd4..dc3b6f46 100644 --- a/ui/src/ui.rs +++ b/ui/src/ui.rs @@ -1,7 +1,7 @@ //! General functions. use ffi_utils::{self, Text}; -use libc::{c_char, c_void}; +use libc::{c_char, c_int, c_void}; use std::fmt::{self, Debug, Formatter}; use std::ffi::{CStr, CString}; use std::mem; @@ -46,6 +46,20 @@ pub fn main() { } } +#[inline] +pub fn main_steps() { + unsafe { + ui_sys::uiMainSteps() + } +} + +#[inline] +pub fn main_step(wait: bool) -> bool { + unsafe { + ui_sys::uiMainStep(wait as c_int) != 0 + } +} + #[inline] pub fn quit() { unsafe { @@ -131,4 +145,3 @@ pub fn msg_box_error(parent: &Window, title: &str, description: &str) { ui_sys::uiMsgBoxError(parent.as_ui_window(), c_title.as_ptr(), c_description.as_ptr()) } } - diff --git a/ui/src/windows.rs b/ui/src/windows.rs index c43ff049..46cf9ab6 100644 --- a/ui/src/windows.rs +++ b/ui/src/windows.rs @@ -37,6 +37,112 @@ impl Window { } } + #[inline] + pub fn position(&self) -> (i32, i32) { + ffi_utils::ensure_initialized(); + let mut x: c_int = 0; + let mut y: c_int = 0; + unsafe { + ui_sys::uiWindowPosition(self.ui_window, &mut x, &mut y); + } + (x, y) + } + + #[inline] + pub fn set_position(&self, x: i32, y: i32) { + ffi_utils::ensure_initialized(); + unsafe { + ui_sys::uiWindowSetPosition(self.ui_window, x as c_int, y as c_int) + } + } + + #[inline] + pub fn center(&self) { + ffi_utils::ensure_initialized(); + unsafe { + ui_sys::uiWindowCenter(self.ui_window) + } + } + + #[inline] + pub fn on_position_changed(&self, callback: Box) { + ffi_utils::ensure_initialized(); + unsafe { + let mut data: Box> = Box::new(callback); + ui_sys::uiWindowOnPositionChanged(self.ui_window, + c_callback, + &mut *data as *mut Box as + *mut c_void); + mem::forget(data); + } + + extern "C" fn c_callback(window: *mut uiWindow, data: *mut c_void) { + unsafe { + let window = Window { + ui_window: window, + }; + mem::transmute::<*mut c_void, &mut Box>(data)(&window) + } + } + } + + #[inline] + pub fn content_size(&self) -> (i32, i32) { + ffi_utils::ensure_initialized(); + let mut width: c_int = 0; + let mut height: c_int = 0; + unsafe { + ui_sys::uiWindowContentSize(self.ui_window, &mut width, &mut height); + } + (width, height) + } + + #[inline] + pub fn set_content_size(&self, width: i32, height: i32) { + ffi_utils::ensure_initialized(); + unsafe { + ui_sys::uiWindowSetContentSize(self.ui_window, width as c_int, height as c_int) + } + } + + #[inline] + pub fn fullscreen(&self) -> bool { + ffi_utils::ensure_initialized(); + unsafe { + ui_sys::uiWindowFullscreen(self.ui_window) != 0 + } + } + + #[inline] + pub fn set_fullscreen(&self, fullscreen: bool) { + ffi_utils::ensure_initialized(); + unsafe { + ui_sys::uiWindowSetFullscreen(self.ui_window, fullscreen as c_int) + } + } + + #[inline] + pub fn on_content_size_changed(&self, callback: Box) { + ffi_utils::ensure_initialized(); + unsafe { + let mut data: Box> = Box::new(callback); + ui_sys::uiWindowOnContentSizeChanged(self.ui_window, + c_callback, + &mut *data as *mut Box as + *mut c_void); + mem::forget(data); + } + + extern "C" fn c_callback(window: *mut uiWindow, data: *mut c_void) { + unsafe { + let window = Window { + ui_window: window, + }; + mem::transmute::<*mut c_void, &mut Box>(data)(&window) + } + } + } + #[inline] pub fn on_closing(&self, callback: Box bool>) { ffi_utils::ensure_initialized(); @@ -60,6 +166,22 @@ impl Window { } } + #[inline] + pub fn borderless(&self) -> bool { + ffi_utils::ensure_initialized(); + unsafe { + ui_sys::uiWindowBorderless(self.ui_window) != 0 + } + } + + #[inline] + pub fn set_borderless(&self, borderless: bool) { + ffi_utils::ensure_initialized(); + unsafe { + ui_sys::uiWindowSetBorderless(self.ui_window, borderless as c_int) + } + } + #[inline] pub fn set_child(&self, child: Control) { ffi_utils::ensure_initialized(); @@ -116,4 +238,3 @@ impl Window { }) } } -