├── .clang-format ├── .gitignore ├── .gitmodules ├── Cargo.toml ├── LICENSE ├── README.md ├── bind.sh ├── examples └── simple.rs ├── floui-sys ├── .gitignore ├── CMakeLists.txt ├── Cargo.toml ├── README.md ├── build.rs └── src │ ├── floui.cpp │ ├── floui.h │ ├── floui.mm │ ├── floui.rs │ └── lib.rs └── src ├── enums.rs ├── lib.rs ├── prelude.rs └── widgets ├── button.rs ├── misc.rs ├── mod.rs ├── stack.rs └── text.rs /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: ObjC 3 | AccessModifierOffset: -2 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveAssignments: false 6 | AlignConsecutiveDeclarations: false 7 | AlignEscapedNewlines: Right 8 | AlignOperands: true 9 | AlignTrailingComments: true 10 | AllowAllParametersOfDeclarationOnNextLine: true 11 | AllowShortBlocksOnASingleLine: false 12 | AllowShortCaseLabelsOnASingleLine: false 13 | AllowShortFunctionsOnASingleLine: true 14 | AllowShortIfStatementsOnASingleLine: false 15 | AllowShortLoopsOnASingleLine: false 16 | AlwaysBreakAfterDefinitionReturnType: None 17 | AlwaysBreakAfterReturnType: None 18 | AlwaysBreakBeforeMultilineStrings: false 19 | AlwaysBreakTemplateDeclarations: true 20 | BinPackArguments: true 21 | BinPackParameters: true 22 | BreakBeforeBraces: Custom 23 | BraceWrapping: 24 | AfterClass: false 25 | AfterControlStatement: false 26 | AfterEnum: false 27 | AfterFunction: false 28 | AfterNamespace: false 29 | AfterObjCDeclaration: false 30 | AfterStruct: false 31 | AfterUnion: false 32 | AfterExternBlock: false 33 | BeforeCatch: false 34 | BeforeElse: false 35 | IndentBraces: false 36 | SplitEmptyFunction: false 37 | SplitEmptyRecord: false 38 | SplitEmptyNamespace: false 39 | BreakBeforeBinaryOperators: None 40 | BreakBeforeInheritanceComma: false 41 | BreakBeforeTernaryOperators: true 42 | BreakConstructorInitializersBeforeComma: false 43 | BreakConstructorInitializers: BeforeColon 44 | BreakStringLiterals: true 45 | ColumnLimit: 100 46 | CommentPragmas: '^ IWYU pragma:' 47 | CompactNamespaces: false 48 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 49 | ConstructorInitializerIndentWidth: 4 50 | ContinuationIndentWidth: 4 51 | Cpp11BracedListStyle: true 52 | DerivePointerAlignment: false 53 | DisableFormat: false 54 | ExperimentalAutoDetectBinPacking: false 55 | FixNamespaceComments: true 56 | IncludeBlocks: Preserve 57 | IndentCaseLabels: false 58 | IndentPPDirectives: None 59 | IndentWidth: 4 60 | IndentWrappedFunctionNames: false 61 | KeepEmptyLinesAtTheStartOfBlocks: true 62 | MacroBlockBegin: '' 63 | MacroBlockEnd: '' 64 | MaxEmptyLinesToKeep: 1 65 | NamespaceIndentation: None 66 | PenaltyBreakAssignment: 2 67 | PenaltyBreakBeforeFirstCallParameter: 19 68 | PenaltyBreakComment: 300 69 | PenaltyBreakFirstLessLess: 120 70 | PenaltyBreakString: 1000 71 | PenaltyExcessCharacter: 1000000 72 | PenaltyReturnTypeOnItsOwnLine: 60 73 | PointerAlignment: Right 74 | ReflowComments: true 75 | SortIncludes: true 76 | SortUsingDeclarations: true 77 | SpaceAfterCStyleCast: false 78 | SpaceAfterTemplateKeyword: true 79 | SpaceBeforeAssignmentOperators: true 80 | SpaceBeforeParens: ControlStatements 81 | SpaceInEmptyParentheses: false 82 | SpacesBeforeTrailingComments: 1 83 | SpacesInAngles: false 84 | SpacesInContainerLiterals: true 85 | SpacesInCStyleCastParentheses: false 86 | SpacesInParentheses: false 87 | SpacesInSquareBrackets: false 88 | Standard: Cpp11 89 | TabWidth: 8 90 | UseTab: Never 91 | --- 92 | Language: Cpp 93 | AccessModifierOffset: -2 94 | AlignAfterOpenBracket: Align 95 | AlignConsecutiveAssignments: false 96 | AlignConsecutiveDeclarations: false 97 | AlignEscapedNewlines: Right 98 | AlignOperands: true 99 | AlignTrailingComments: true 100 | AllowAllParametersOfDeclarationOnNextLine: true 101 | AllowShortBlocksOnASingleLine: false 102 | AllowShortCaseLabelsOnASingleLine: false 103 | AllowShortFunctionsOnASingleLine: true 104 | AllowShortIfStatementsOnASingleLine: false 105 | AllowShortLoopsOnASingleLine: false 106 | AlwaysBreakAfterDefinitionReturnType: None 107 | AlwaysBreakAfterReturnType: None 108 | AlwaysBreakBeforeMultilineStrings: false 109 | AlwaysBreakTemplateDeclarations: true 110 | BinPackArguments: true 111 | BinPackParameters: true 112 | BreakBeforeBraces: Custom 113 | BraceWrapping: 114 | AfterClass: false 115 | AfterControlStatement: false 116 | AfterEnum: false 117 | AfterFunction: false 118 | AfterNamespace: false 119 | AfterObjCDeclaration: false 120 | AfterStruct: false 121 | AfterUnion: false 122 | AfterExternBlock: false 123 | BeforeCatch: false 124 | BeforeElse: false 125 | IndentBraces: false 126 | SplitEmptyFunction: false 127 | SplitEmptyRecord: false 128 | SplitEmptyNamespace: false 129 | BreakBeforeBinaryOperators: None 130 | BreakBeforeInheritanceComma: false 131 | BreakBeforeTernaryOperators: true 132 | BreakConstructorInitializersBeforeComma: false 133 | BreakConstructorInitializers: BeforeColon 134 | BreakStringLiterals: true 135 | ColumnLimit: 100 136 | CommentPragmas: '^ IWYU pragma:' 137 | CompactNamespaces: false 138 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 139 | ConstructorInitializerIndentWidth: 4 140 | ContinuationIndentWidth: 4 141 | Cpp11BracedListStyle: true 142 | DerivePointerAlignment: false 143 | DisableFormat: false 144 | ExperimentalAutoDetectBinPacking: false 145 | FixNamespaceComments: true 146 | IncludeBlocks: Preserve 147 | IndentCaseLabels: false 148 | IndentPPDirectives: None 149 | IndentWidth: 4 150 | IndentWrappedFunctionNames: false 151 | KeepEmptyLinesAtTheStartOfBlocks: true 152 | MacroBlockBegin: '' 153 | MacroBlockEnd: '' 154 | MaxEmptyLinesToKeep: 1 155 | NamespaceIndentation: None 156 | PenaltyBreakAssignment: 2 157 | PenaltyBreakBeforeFirstCallParameter: 19 158 | PenaltyBreakComment: 300 159 | PenaltyBreakFirstLessLess: 120 160 | PenaltyBreakString: 1000 161 | PenaltyExcessCharacter: 1000000 162 | PenaltyReturnTypeOnItsOwnLine: 60 163 | PointerAlignment: Right 164 | ReflowComments: true 165 | SortIncludes: true 166 | SortUsingDeclarations: true 167 | SpaceAfterCStyleCast: false 168 | SpaceAfterTemplateKeyword: true 169 | SpaceBeforeAssignmentOperators: true 170 | SpaceBeforeParens: ControlStatements 171 | SpaceInEmptyParentheses: false 172 | SpacesBeforeTrailingComments: 1 173 | SpacesInAngles: false 174 | SpacesInContainerLiterals: true 175 | SpacesInCStyleCastParentheses: false 176 | SpacesInParentheses: false 177 | SpacesInSquareBrackets: false 178 | Standard: Cpp11 179 | TabWidth: 8 180 | UseTab: Never 181 | ... 182 | 183 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | .DS_Store 4 | temp.c -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "floui-sys/floui"] 2 | path = floui-sys/floui 3 | url = https://github.com/MoAlyousef/floui 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "floui" 3 | version = "0.1.5" 4 | edition = "2021" 5 | description = "A SwiftUI inspired native wrapper for iOS and Android widgets" 6 | repository = "https://github.com/MoAlyousef/floui-rs" 7 | documentation = "https://docs.rs/floui" 8 | keywords = ["gui", "ui", "widgets", "bindings", "mobile"] 9 | categories = ["gui"] 10 | readme = "README.md" 11 | license = "MIT" 12 | 13 | [dependencies] 14 | floui-sys = { version = "=0.1.4", path = "floui-sys" } 15 | lazy_static = "1.4" 16 | 17 | [features] 18 | ios-webview = ["floui-sys/ios-webview"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Mohammed Alyousef 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # floui-rs 2 | 3 | Rust bindings for [floui](https://github.com/MoAlyousef/floui), pronounced "flowy", a proof-of-concept single header C++17 lib inspired by SwiftUI, which wraps native iOS and Android controls/widgets, and integrates into the de facto build environments of each platform (XCode and Android Studio). 4 | 5 | ![image](https://user-images.githubusercontent.com/37966791/178625452-4edc4d01-157e-413c-9610-826a94f407e7.png) 6 | 7 | ## Currently available controls: 8 | - Text 9 | - TextField 10 | - Button 11 | - VStack (Vertical UIStackView on iOS and LinearLayout on Android) 12 | - HStack (Horizontal UIStackView on iOS and LinearLayout on Android) 13 | - Spacer 14 | - Toggle/Check (tvOS doesn't support it) 15 | - Slider (tvOS doesn't support it) 16 | - ImageView 17 | - WebView 18 | - ScrollView 19 | 20 | ## Usage 21 | You can check out the [floui-rs-template](https://github.com/MoAlyousef/floui-rs-template), which is structured to be able to build for both ios or android from the command-line. 22 | 23 | If you would like to build purely for iOS and only using Rust (no Objective-C), check the example [here](https://github.com/MoAlyousef/floui-rs-ios). 24 | 25 | Otherwise, if you would like to do it manually: 26 | 27 | Build your library as a static-lib: 28 | ```toml 29 | # Cargo.toml 30 | [lib] 31 | crate-type = ["static-lib"] 32 | 33 | [dependencies] 34 | floui = "0.1" 35 | ``` 36 | Build against the android and ios architectures you might need. 37 | 38 | ### Rust 39 | ```rust 40 | use floui::{enums::*, prelude::*, widgets::*}; 41 | use std::cell::RefCell; 42 | use std::rc::Rc; 43 | 44 | fn mygui(vc: &ViewController) -> MainView { 45 | let count = Rc::from(RefCell::from(0)); 46 | MainView::new( 47 | &vc, 48 | &[ 49 | &Button::new("Increment").foreground(Color::Blue).action({ 50 | let count = count.clone(); 51 | move |_| { 52 | log("Increment clicked"); 53 | let mut c = count.borrow_mut(); 54 | *c += 1; 55 | let t: Text = from_id("mytext").unwrap(); 56 | t.text(&format!("{}", c)); 57 | } 58 | }), 59 | &Text::new("0").id("mytext").center().bold(), 60 | &Button::new("Decrement") 61 | .foreground(Color::Red) 62 | .action(move |_| { 63 | log("Decrement clicked"); 64 | let mut c = count.borrow_mut(); 65 | *c -= 1; 66 | let t: Text = from_id("mytext").unwrap(); 67 | t.text(&format!("{}", c)); 68 | }), 69 | ], 70 | ) 71 | } 72 | 73 | use std::os::raw::c_void; 74 | 75 | #[no_mangle] 76 | extern "C" fn floui_handle_events(arg1: *mut c_void) { 77 | unsafe { ViewController::handle_events(arg1); } 78 | } 79 | 80 | #[no_mangle] 81 | extern "C" fn floui_main(arg1: *mut c_void, arg2: *mut c_void, arg3: *mut c_void) -> *mut c_void { 82 | let vc = unsafe { ViewController::new(arg1, arg2, arg3) }; 83 | mygui(&vc).underlying() as _ 84 | } 85 | ``` 86 | 87 | ## Notes on certain usages 88 | - Sliders on Android take the full width of the LinearLayout, so this must be taken into consideration if code is shared also with iOS. 89 | - Adding images has to be in the project's resource file. 90 | - In Android Studio: Resource Manager, Import Drawables. This will add the file to res/drawable. The file can be accessed directly ImageView::load("MyImage.jpg"). 91 | - In XCode: You can simply drag images into Assets.xcassets, then the image can be accessed directly ImageView::load("MyImage.jpg"). 92 | 93 | - Using the WebView widget 94 | - on iOS: 95 | - Requires adding WebKit.framework under General > Frameworks, Libraries and Embedded Content. 96 | - Requires enabling the `ios-webview` flag in your Cargo.toml. 97 | - Local files can be loaded using WebView::load_url() but need to be preceded by `file:///`, the files should be added to your xcode project. 98 | - On Android: 99 | - To load local files, precede them with `file:///` and the path of the file, which should be added to an assets folder (File > New > Folder > Assets folder). This then can be loaded using WebView::load_url(). 100 | - To load http requests, you need to enable the internet permission in your AndroidManifest.xml: `` 101 | 102 | ## Creating new widgets 103 | Wrapping platform widgets doesn't require using C++, it requires that the widget implements WidgetExt, and the underlying (JNI jobject pointer for Android, UIView on iOS) can be retrieved. You can use the jni-rs crate and objc crates for such purposes. 104 | 105 | ## Target-specific structure 106 | ### iOS 107 | - Add the required ios rustup targets. 108 | - Install cargo-lipo. 109 | - Add the built library to your xcode project (under Build Phases > Link Binary with Libraries). 110 | - Modify the library search path to find the library (under Build Settings > Library Search Paths). 111 | - Modify your ViewController.m file: 112 | ```objc 113 | #import "ViewController.h" 114 | 115 | extern void *floui_main(void *, void *, void *); 116 | 117 | @interface ViewController () 118 | 119 | @end 120 | 121 | @implementation ViewController 122 | - (void)viewDidLoad { 123 | [super viewDidLoad]; 124 | floui_main((void *)CFBridgingRetain(self), nil, nil); 125 | } 126 | 127 | @end 128 | ``` 129 | 130 | ### Android 131 | - ANDROID_SDK_ROOT should be set to your android sdk directory. 132 | - ANDROID_NDK_ROOT should be set to your android ndk directory. 133 | - Add the required android rustup targets. 134 | - Create an Android Studio Native C++ project, choose toolchain C++ 17 in the last step. 135 | - Modify your CMakeLists.txt: 136 | ```cmake 137 | cmake_minimum_required(VERSION 3.4.1) 138 | project(myapplication) 139 | 140 | find_library(log-lib log) 141 | 142 | add_library(myapplication SHARED native-lib.cpp) 143 | add_library(rust-lib STATIC IMPORTED) 144 | 145 | if (ANDROID_ABI STREQUAL x86) 146 | set(RUST_ARCH i686-linux-android) 147 | elseif (ANDROID_ABI STREQUAL armeabi-v7a) 148 | set(RUST_ARCH armv7-linux-androideabi) 149 | elseif (ANDROID_ABI STREQUAL arm64-v8a) 150 | set(RUST_ARCH aarch64-linux-android) 151 | elseif (ANDROID_ABI STREQUAL x86_64) 152 | set(RUST_ARCH x86_64-linux-android) 153 | else () 154 | message(FATAL "Unknown architecture") 155 | endif () 156 | 157 | set_property(TARGET rust-lib PROPERTY IMPORTED_LOCATION_DEBUG ${CMAKE_CURRENT_LIST_DIR}/app/target/${RUST_ARCH}/debug/libapp.a) 158 | set_property(TARGET rust-lib PROPERTY IMPORTED_LOCATION_RELEASE ${CMAKE_CURRENT_LIST_DIR}/app/target/${RUST_ARCH}/release/libapp.a) 159 | 160 | target_link_libraries(myapplication android rust-lib ${log-lib}) 161 | ``` 162 | - Modify your C++ file to just call the Rust lib. 163 | ```c++ 164 | #include 165 | #include 166 | 167 | extern "C" void *floui_main(void *, void *, void *); 168 | 169 | extern "C" void floui_handle_events(void *); 170 | 171 | extern "C" JNIEXPORT jobject JNICALL 172 | Java_com_example_myapplication_MainActivity_mainView(JNIEnv* env, jobject main_activity, jobject view) { 173 | return (jobject) floui_main(env, main_activity, view); 174 | } 175 | 176 | extern "C" JNIEXPORT void JNICALL 177 | Java_com_example_myapplication_MainActivity_handleEvent(JNIEnv *env, jobject thiz, jobject view) { 178 | floui_handle_events(view); 179 | } 180 | ``` 181 | - Modify your MainActivity.java to look like: 182 | ```java 183 | package com.example.myapplication; 184 | 185 | import androidx.annotation.NonNull; 186 | import androidx.appcompat.app.AppCompatActivity; 187 | import androidx.constraintlayout.widget.ConstraintLayout; 188 | 189 | import android.os.Bundle; 190 | import android.view.View; 191 | 192 | import com.google.android.material.slider.Slider; 193 | 194 | public class MainActivity extends AppCompatActivity implements View.OnClickListener, Slider.OnChangeListener { 195 | static { 196 | System.loadLibrary("myapplication"); 197 | } 198 | 199 | @Override 200 | protected void onCreate(Bundle savedInstanceState) { 201 | super.onCreate(savedInstanceState); 202 | ConstraintLayout layout = new ConstraintLayout(this); 203 | setContentView(layout); 204 | mainView(layout); 205 | } 206 | public native View mainView(View view); 207 | public native void handleEvent(View view); 208 | 209 | @Override 210 | public void onClick(View view) { 211 | handleEvent(view); 212 | } 213 | 214 | @Override 215 | public void onValueChange(@NonNull Slider slider, float value, boolean fromUser) { 216 | handleEvent(slider); 217 | } 218 | } 219 | ``` 220 | -------------------------------------------------------------------------------- /bind.sh: -------------------------------------------------------------------------------- 1 | bindgen floui-sys/src/floui.h -o floui-sys/src/floui.rs -------------------------------------------------------------------------------- /examples/simple.rs: -------------------------------------------------------------------------------- 1 | use floui::{enums::*, prelude::*, widgets::*}; 2 | use std::cell::RefCell; 3 | use std::rc::Rc; 4 | 5 | fn mygui(vc: &ViewController) -> MainView { 6 | let count = Rc::from(RefCell::from(0)); 7 | MainView::new( 8 | &vc, 9 | &[ 10 | &Button::new("Increment").foreground(Color::Blue).action({ 11 | let count = count.clone(); 12 | move |_| { 13 | log("Increment clicked"); 14 | let mut c = count.borrow_mut(); 15 | *c += 1; 16 | let t: Text = from_id("mytext").unwrap(); 17 | t.text(&format!("{}", c)); 18 | } 19 | }), 20 | &Text::new("0").id("mytext").center().bold(), 21 | &Button::new("Decrement") 22 | .foreground(Color::Red) 23 | .action(move |_| { 24 | log("Decrement clicked"); 25 | let mut c = count.borrow_mut(); 26 | *c -= 1; 27 | let t: Text = from_id("mytext").unwrap(); 28 | t.text(&format!("{}", c)); 29 | }), 30 | ], 31 | ) 32 | } 33 | 34 | use std::os::raw::c_void; 35 | 36 | #[no_mangle] 37 | extern "C" fn floui_main(arg1: *mut c_void, arg2: *mut c_void, arg3: *mut c_void) -> *mut c_void { 38 | let vc = unsafe { ViewController::new(arg1, arg2, arg3) }; 39 | mygui(&vc).underlying() as _ 40 | } 41 | 42 | #[no_mangle] 43 | extern "C" fn floui_handle_events(arg1: *mut c_void) { 44 | unsafe { ViewController::handle_events(arg1); } 45 | } 46 | 47 | fn main() {} 48 | -------------------------------------------------------------------------------- /floui-sys/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | .DS_Store 4 | temp.c -------------------------------------------------------------------------------- /floui-sys/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(floui_lib) 3 | 4 | add_library(floui STATIC src/floui.cpp) 5 | target_compile_features(floui PRIVATE cxx_std_17) 6 | 7 | install(TARGETS floui 8 | DESTINATION ${CMAKE_INSTALL_PREFIX} 9 | ) -------------------------------------------------------------------------------- /floui-sys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "floui-sys" 3 | version = "0.1.4" 4 | edition = "2021" 5 | description = "A SwiftUI inspired native wrapper for iOS and Android widgets" 6 | repository = "https://github.com/MoAlyousef/floui-rs" 7 | documentation = "https://docs.rs/floui" 8 | keywords = ["gui", "ui", "widgets", "bindings", "mobile"] 9 | categories = ["gui"] 10 | readme = "README.md" 11 | license = "MIT" 12 | 13 | [target.'cfg(not(android))'.build-dependencies] 14 | cc = "1" 15 | 16 | [features] 17 | ios-webview = [] -------------------------------------------------------------------------------- /floui-sys/README.md: -------------------------------------------------------------------------------- 1 | # floui-sys 2 | 3 | The raw bindings to floui. -------------------------------------------------------------------------------- /floui-sys/build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs; 3 | use std::path::{Path, PathBuf}; 4 | use std::process::Command; 5 | 6 | fn main() { 7 | println!("cargo:rerun-if-changed=src/floui.h"); 8 | println!("cargo:rerun-if-changed=src/floui.mm"); 9 | println!("cargo:rerun-if-changed=src/floui.cpp"); 10 | println!("cargo:rerun-if-changed=src/floui.rs"); 11 | let target = env::var("TARGET").unwrap(); 12 | if target.contains("ios") { 13 | let sdk = if target.contains("sim") { 14 | "iphonesimulator" 15 | } else { 16 | "iphoneos" 17 | }; 18 | let sdk = String::from_utf8( 19 | Command::new("xcrun") 20 | .args(&["--sdk", sdk, "--show-sdk-path"]) 21 | .output() 22 | .expect("Couldn't run xcrun! Verify your XCode installation.") 23 | .stdout, 24 | ) 25 | .unwrap(); 26 | println!("cargo:rustc-link-lib=framework=UIKit"); 27 | println!("cargo:rustc-link-lib=framework=WebKit"); 28 | let mut cc = cc::Build::new(); 29 | if cfg!(feature = "ios-webview") { 30 | cc.define("FLOUI_IOS_WEBVIEW", None); 31 | } 32 | cc.file("src/floui.mm") 33 | .cpp(true) 34 | .flag_if_supported(&format!("-isysroot={}", sdk)) 35 | .flag_if_supported("-std=c++17") 36 | .flag_if_supported("-w") 37 | .compile("floui"); 38 | } else if target.contains("android") { 39 | println!("cargo:rerun-if-changed=CMakeLists.txt"); 40 | println!("cargo:rerun-if-env-changed=ANDROID_SDK_ROOT"); 41 | println!("cargo:rerun-if-env-changed=ANDROID_NDK_ROOT"); 42 | let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); 43 | let sdk = 44 | PathBuf::from(env::var("ANDROID_SDK_ROOT").expect("ANDROID_SDK_ROOT should be set!")); 45 | let ndk = 46 | PathBuf::from(env::var("ANDROID_NDK_ROOT").expect("ANDROID_NDK_ROOT should be set!")); 47 | let target_triple = env::var("TARGET").unwrap(); 48 | let cmake_build_dir = out_dir.join("cmake_build").to_str().unwrap().to_string(); 49 | let mut cmd = vec![]; 50 | cmd.push(format!("-B{}", cmake_build_dir)); 51 | cmd.push("-DCMAKE_BUILD_TYPE=Release".to_string()); 52 | cmd.push(format!( 53 | "-DCMAKE_INSTALL_PREFIX={}", 54 | out_dir.to_str().unwrap() 55 | )); 56 | cmd.push("-GNinja".to_string()); 57 | cmd.push("-DCMAKE_SYSTEM_NAME=Android".to_string()); 58 | cmd.push("-DCMAKE_SYSTEM_VERSION=21".to_string()); 59 | cmd.push("-DANDROID_PLATFORM=android-21".to_string()); 60 | cmd.push(format!("-DCMAKE_ANDROID_NDK={}", &ndk.to_str().unwrap())); 61 | cmd.push(format!("-DANDROID_NDK={}", &ndk.to_str().unwrap())); 62 | cmd.push(format!( 63 | "-DCMAKE_MAKE_PROGRAM={}", 64 | find_ninja(&sdk) 65 | .expect("Couldn't find NDK ninja!") 66 | .to_str() 67 | .unwrap() 68 | )); 69 | cmd.push(format!( 70 | "-DCMAKE_TOOLCHAIN_FILE={}", 71 | ndk.join("build") 72 | .join("cmake") 73 | .join("android.toolchain.cmake") 74 | .to_str() 75 | .unwrap() 76 | )); 77 | match target_triple.as_str() { 78 | "i686-linux-android" => { 79 | cmd.push("-DANDROID_ABI=x86".to_string()); 80 | cmd.push("-DCMAKE_ANDROID_ARCH_ABI=x86".to_string()); 81 | } 82 | "aarch64-linux-android" => { 83 | cmd.push("-DANDROID_ABI=arm64-v8a".to_string()); 84 | cmd.push("-DCMAKE_ANDROID_ARCH_ABI=arm64-v8a".to_string()); 85 | } 86 | "armv7-linux-androideabi" => { 87 | cmd.push("-DANDROID_ABI=armeabi-v7a".to_string()); 88 | cmd.push("-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a".to_string()); 89 | } 90 | "x86_64-linux-android" => { 91 | cmd.push("-DANDROID_ABI=x86_64".to_string()); 92 | cmd.push("-DCMAKE_ANDROID_ARCH_ABI=x86_64".to_string()); 93 | } 94 | _ => panic!("Unknown android triple"), 95 | } 96 | Command::new("cmake") 97 | .args(&cmd) 98 | .current_dir(".") 99 | .status() 100 | .expect("CMake is needed for android builds!"); 101 | Command::new("cmake") 102 | .args(&["--build", &cmake_build_dir, "--target", "install"]) 103 | .current_dir(".") 104 | .status() 105 | .expect("CMake is needed for android builds!"); 106 | println!("cargo:rustc-link-search=native={}", out_dir.display()); 107 | println!("cargo:rustc-link-lib=static=floui"); 108 | } else { 109 | println!("cargo:warning=Building against the current arch!"); 110 | // let host = env::var("HOST").unwrap(); 111 | // let host = if host.contains("windows") { 112 | // "win32" 113 | // } else if host.contains("apple-darwin") { 114 | // "darwin" 115 | // } else { 116 | // "linux" 117 | // }; 118 | // let include_path = env::var("JAVA_HOME").expect("JAVA_HOME should be set!"); 119 | // let include_path = PathBuf::from(include_path); 120 | // cc::Build::new() 121 | // .file("src/floui.cpp") 122 | // .cpp(true) 123 | // .include(include_path.join("include")) 124 | // .include(include_path.join(&format!("include/{}", host))) 125 | // .flag_if_supported("-std=c++17") 126 | // .flag_if_supported("-w") 127 | // .compile("floui"); 128 | } 129 | } 130 | 131 | fn find_ninja(sdk_path: &Path) -> Option { 132 | let cmk = sdk_path.join("cmake"); 133 | for subdir in fs::read_dir(cmk).unwrap() { 134 | let subdir = subdir 135 | .unwrap() // Shouldn't fail! 136 | .path() 137 | .file_name() 138 | .unwrap() 139 | .to_str() 140 | .unwrap() 141 | .to_owned(); 142 | if subdir.starts_with("3.") { 143 | return Some( 144 | sdk_path 145 | .join("cmake") 146 | .join(subdir) 147 | .join("bin") 148 | .join("ninja"), 149 | ); 150 | } 151 | } 152 | None 153 | } 154 | -------------------------------------------------------------------------------- /floui-sys/src/floui.cpp: -------------------------------------------------------------------------------- 1 | #include "floui.h" 2 | 3 | #define FLOUI_IMPL 4 | #include "../floui/floui.hpp" 5 | 6 | void Cfloui_log(const char *s) { floui_log(s); } 7 | 8 | #define DEFINE_SHARED_METHODS(x) \ 9 | void x##_id(x *self, const char *id) { ((Widget *)self)->id(id); } \ 10 | void x##_background(x *self, unsigned int col) { ((Widget *)self)->background(col); } \ 11 | void x##_size(x *self, int w, int h) { ((Widget *)self)->size(w, h); } \ 12 | void *x##_inner(x *self) { return ((Widget *)self)->inner(); } 13 | 14 | #define DEFINE_SHARED_GROUP_METHODS(x) \ 15 | void x##_add(x *self, const CWidget *w) { ((VStack *)self)->add(*(Widget *)w); } \ 16 | void x##_remove(x *self, const CWidget *w) { ((VStack *)self)->remove(*(Widget *)w); } \ 17 | void x##_clear(x *self) { ((VStack *)self)->clear(); } \ 18 | void x##_spacing(x *self, int spacing) { ((VStack *)self)->spacing(spacing); } 19 | 20 | CFlouiViewController *CFlouiViewController_new(void *arg1, void *arg2, void *arg3) { 21 | return (CFlouiViewController *)new FlouiViewController(arg1, arg2, arg3); 22 | } 23 | 24 | void CFlouiViewController_handle_events(void *view) { FlouiViewController::handle_events(view); } 25 | 26 | DEFINE_SHARED_METHODS(CWidget) 27 | 28 | CMainView *CMainView_new(const CFlouiViewController *fvc) { 29 | return (CMainView *)new MainView(*(FlouiViewController *)fvc, {}); 30 | } 31 | 32 | DEFINE_SHARED_METHODS(CMainView) 33 | 34 | DEFINE_SHARED_GROUP_METHODS(CMainView) 35 | 36 | CVStack *CVStack_new(void) { return (CVStack *)new VStack({}); } 37 | 38 | DEFINE_SHARED_METHODS(CVStack) 39 | 40 | DEFINE_SHARED_GROUP_METHODS(CVStack) 41 | 42 | CHStack *CHStack_new(void) { return (CHStack *)new HStack({}); } 43 | 44 | DEFINE_SHARED_METHODS(CHStack) 45 | 46 | DEFINE_SHARED_GROUP_METHODS(CHStack) 47 | 48 | CButton *CButton_new(const char *label) { return (CButton *)new Button(label); } 49 | 50 | DEFINE_SHARED_METHODS(CButton) 51 | 52 | void CButton_action(CButton *self, CFlouiCallback cb, void *data) { 53 | ((Button *)self)->action([=](Widget &) { (*cb)((CWidget *)self, data); }); 54 | } 55 | 56 | void CButton_filled(CButton *self) { ((Button *)self)->filled(); } 57 | 58 | void CButton_foreground(CButton *self, unsigned int c) { ((Button *)self)->foreground(c); } 59 | 60 | DEFINE_SHARED_METHODS(CToggle) 61 | 62 | CToggle *CToggle_new(const char *label) { return (CToggle *)new Toggle(label); } 63 | 64 | void CToggle_action(CToggle *self, CFlouiCallback cb, void *data) { 65 | ((Toggle *)self)->action([=](Widget &) { (*cb)((CWidget *)self, data); }); 66 | } 67 | 68 | void CToggle_set_value(CToggle *self, int val) { ((Toggle *)self)->value(val); } 69 | 70 | int CToggle_value(CToggle *self) { return ((Toggle *)self)->value(); } 71 | 72 | void CToggle_foreground(CToggle *self, unsigned int c) { ((Toggle *)self)->foreground(c); } 73 | 74 | DEFINE_SHARED_METHODS(CCheck) 75 | 76 | CCheck *CCheck_new(const char *label) { return (CCheck *)new Check(label); } 77 | 78 | void CCheck_action(CCheck *self, CFlouiCallback cb, void *data) { 79 | ((Check *)self)->action([=](Widget &) { (*cb)((CWidget *)self, data); }); 80 | } 81 | 82 | void CCheck_set_value(CCheck *self, int val) { ((Check *)self)->value(val); } 83 | 84 | int CCheck_value(CCheck *self) { return ((Check *)self)->value(); } 85 | 86 | void CCheck_foreground(CCheck *self, unsigned int c) { ((Check *)self)->foreground(c); } 87 | 88 | DEFINE_SHARED_METHODS(CSlider) 89 | 90 | CSlider *CSlider_new() { return (CSlider *)new Slider(); } 91 | 92 | void CSlider_action(CSlider *self, CFlouiCallback cb, void *data) { 93 | ((Slider *)self)->action([=](Widget &) { (*cb)((CWidget *)self, data); }); 94 | } 95 | 96 | void CSlider_set_value(CSlider *self, double val) { ((Slider *)self)->value(val); } 97 | 98 | double CSlider_value(CSlider *self) { return ((Slider *)self)->value(); } 99 | 100 | void CSlider_foreground(CSlider *self, unsigned int c) { ((Slider *)self)->foreground(c); } 101 | 102 | CText *CText_new(const char *label) { return (CText *)new Text(label); } 103 | 104 | DEFINE_SHARED_METHODS(CText) 105 | 106 | void CText_text(CText *self, const char *t) { ((Text *)self)->text(t); } 107 | 108 | void CText_center(CText *self) { ((Text *)self)->center(); } 109 | 110 | void CText_left(CText *self) { ((Text *)self)->left(); } 111 | 112 | void CText_right(CText *self) { ((Text *)self)->right(); } 113 | 114 | void CText_bold(CText *self) { ((Text *)self)->bold(); } 115 | 116 | void CText_italic(CText *self) { ((Text *)self)->italic(); } 117 | 118 | void CText_normal(CText *self) { ((Text *)self)->normal(); } 119 | 120 | void CText_foreground(CText *self, unsigned int c) { ((Text *)self)->foreground(c); } 121 | 122 | void CText_fontsize(CText *self, int size) { ((Text *)self)->fontsize(size); } 123 | 124 | CTextField *CTextField_new() { return (CTextField *)new TextField(); } 125 | 126 | DEFINE_SHARED_METHODS(CTextField) 127 | 128 | void CTextField_text(CTextField *self, const char *t) { ((TextField *)self)->text(t); } 129 | 130 | void CTextField_center(CTextField *self) { ((TextField *)self)->center(); } 131 | 132 | void CTextField_left(CTextField *self) { ((TextField *)self)->left(); } 133 | 134 | void CTextField_right(CTextField *self) { ((TextField *)self)->right(); } 135 | 136 | void CTextField_foreground(CTextField *self, unsigned int c) { ((TextField *)self)->foreground(c); } 137 | 138 | void CTextField_fontsize(CTextField *self, int size) { ((TextField *)self)->fontsize(size); } 139 | 140 | CSpacer *CSpacer_new() { return (CSpacer *)new Spacer(); } 141 | 142 | DEFINE_SHARED_METHODS(CSpacer) 143 | 144 | DEFINE_SHARED_METHODS(CImageView) 145 | 146 | CImageView *CImageView_new() { return (CImageView *)new ImageView(); } 147 | 148 | CImageView *CImageView_load(const char *path) { return (CImageView *)new ImageView(path); } 149 | 150 | void CImageView_image(CImageView *self, const char *path) { ((ImageView *)self)->image(path); } 151 | 152 | DEFINE_SHARED_METHODS(CWebView) 153 | 154 | CWebView *CWebView_new() { return (CWebView *)new WebView(); } 155 | 156 | void CWebView_load_url(CWebView *self, const char *url) { ((WebView *)self)->load_url(url); } 157 | 158 | void CWebView_load_html(CWebView *self, const char *html) { ((WebView *)self)->load_html(html); } 159 | 160 | DEFINE_SHARED_METHODS(CScrollView) 161 | 162 | CScrollView *CScrollView_new(const CWidget *w) { 163 | return (CScrollView *)new ScrollView(*(Widget *)w); 164 | } -------------------------------------------------------------------------------- /floui-sys/src/floui.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void Cfloui_log(const char *s); 8 | 9 | #define DECLARE_SHARED_METHODS(x) \ 10 | void x##_id(x *self, const char *id); \ 11 | void x##_background(x *self, unsigned int col); \ 12 | void x##_size(x *self, int w, int h); \ 13 | void *x##_inner(x *self); 14 | 15 | #define DECLARE_SHARED_GROUP_METHODS(x) \ 16 | void x##_add(x *self, const CWidget *w); \ 17 | void x##_remove(x *self, const CWidget *w); \ 18 | void x##_clear(x *self); \ 19 | void x##_spacing(x *self, int spacing); 20 | 21 | typedef struct CFlouiViewController CFlouiViewController; 22 | 23 | CFlouiViewController *CFlouiViewController_new(void *, void *, void *); 24 | 25 | void CFlouiViewController_handle_events(void *); 26 | 27 | typedef struct CWidget CWidget; 28 | 29 | DECLARE_SHARED_METHODS(CWidget); 30 | 31 | typedef void (*CFlouiCallback)(CWidget *, void *data); 32 | 33 | typedef struct CMainView CMainView; 34 | 35 | CMainView *CMainView_new(const CFlouiViewController *fvc); 36 | 37 | DECLARE_SHARED_METHODS(CMainView); 38 | 39 | DECLARE_SHARED_GROUP_METHODS(CMainView); 40 | 41 | typedef struct CVStack CVStack; 42 | 43 | CVStack *CVStack_new(void); 44 | 45 | DECLARE_SHARED_METHODS(CVStack); 46 | 47 | DECLARE_SHARED_GROUP_METHODS(CVStack); 48 | 49 | typedef struct CHStack CHStack; 50 | 51 | CHStack *CHStack_new(void); 52 | 53 | DECLARE_SHARED_METHODS(CHStack); 54 | 55 | DECLARE_SHARED_GROUP_METHODS(CHStack); 56 | 57 | typedef struct CButton CButton; 58 | 59 | DECLARE_SHARED_METHODS(CButton); 60 | 61 | CButton *CButton_new(const char *label); 62 | 63 | void CButton_action(CButton *self, CFlouiCallback cb, void *data); 64 | 65 | void CButton_filled(CButton *self); 66 | 67 | void CButton_foreground(CButton *self, unsigned int c); 68 | 69 | typedef struct CToggle CToggle; 70 | 71 | DECLARE_SHARED_METHODS(CToggle); 72 | 73 | CToggle *CToggle_new(const char *label); 74 | 75 | void CToggle_action(CToggle *self, CFlouiCallback cb, void *data); 76 | 77 | void CToggle_set_value(CToggle *self, int val); 78 | 79 | int CToggle_value(CToggle *self); 80 | 81 | void CToggle_foreground(CToggle *self, unsigned int c); 82 | 83 | typedef struct CCheck CCheck; 84 | 85 | DECLARE_SHARED_METHODS(CCheck); 86 | 87 | CCheck *CCheck_new(const char *label); 88 | 89 | void CCheck_action(CCheck *self, CFlouiCallback cb, void *data); 90 | 91 | void CCheck_set_value(CCheck *self, int val); 92 | 93 | int CCheck_value(CCheck *self); 94 | 95 | void CCheck_foreground(CCheck *self, unsigned int c); 96 | 97 | typedef struct CSlider CSlider; 98 | 99 | DECLARE_SHARED_METHODS(CSlider); 100 | 101 | CSlider *CSlider_new(); 102 | 103 | void CSlider_action(CSlider *self, CFlouiCallback cb, void *data); 104 | 105 | void CSlider_set_value(CSlider *self, double val); 106 | 107 | double CSlider_value(CSlider *self); 108 | 109 | void CSlider_foreground(CSlider *self, unsigned int c); 110 | 111 | typedef struct CText CText; 112 | 113 | DECLARE_SHARED_METHODS(CText); 114 | 115 | CText *CText_new(const char *label); 116 | 117 | void CText_text(CText *self, const char *t); 118 | 119 | void CText_center(CText *self); 120 | 121 | void CText_left(CText *self); 122 | 123 | void CText_right(CText *self); 124 | 125 | void CText_bold(CText *self); 126 | 127 | void CText_italic(CText *self); 128 | 129 | void CText_normal(CText *self); 130 | 131 | void CText_foreground(CText *self, unsigned int c); 132 | 133 | void CText_fontsize(CText *self, int size); 134 | 135 | typedef struct CTextField CTextField; 136 | 137 | DECLARE_SHARED_METHODS(CTextField); 138 | 139 | CTextField *CTextField_new(); 140 | 141 | void CTextField_text(CTextField *self, const char *t); 142 | 143 | void CTextField_center(CTextField *self); 144 | 145 | void CTextField_left(CTextField *self); 146 | 147 | void CTextField_right(CTextField *self); 148 | 149 | void CTextField_foreground(CTextField *self, unsigned int c); 150 | 151 | void CTextField_fontsize(CTextField *self, int size); 152 | 153 | typedef struct CSpacer CSpacer; 154 | 155 | DECLARE_SHARED_METHODS(CSpacer); 156 | 157 | CSpacer *CSpacer_new(); 158 | 159 | typedef struct CImageView CImageView; 160 | 161 | DECLARE_SHARED_METHODS(CImageView); 162 | 163 | CImageView *CImageView_new(); 164 | 165 | CImageView *CImageView_load(const char *path); 166 | 167 | void CImageView_image(CImageView *self, const char *path); 168 | 169 | typedef struct CWebView CWebView; 170 | 171 | DECLARE_SHARED_METHODS(CWebView) 172 | 173 | CWebView *CWebView_new(); 174 | 175 | void CWebView_load_url(CWebView *self, const char *url); 176 | 177 | void CWebView_load_html(CWebView *self, const char *html); 178 | 179 | typedef struct CScrollView CScrollView; 180 | 181 | DECLARE_SHARED_METHODS(CScrollView) 182 | 183 | CScrollView *CScrollView_new(const CWidget *w); 184 | 185 | #ifdef __cplusplus 186 | } 187 | #endif -------------------------------------------------------------------------------- /floui-sys/src/floui.mm: -------------------------------------------------------------------------------- 1 | #include "floui.cpp" 2 | -------------------------------------------------------------------------------- /floui-sys/src/floui.rs: -------------------------------------------------------------------------------- 1 | /* automatically generated by rust-bindgen 0.56.0 */ 2 | 3 | extern "C" { 4 | pub fn Cfloui_log(s: *const ::std::os::raw::c_char); 5 | } 6 | #[repr(C)] 7 | #[derive(Debug, Copy, Clone)] 8 | pub struct CFlouiViewController { 9 | _unused: [u8; 0], 10 | } 11 | extern "C" { 12 | pub fn CFlouiViewController_new( 13 | arg1: *mut ::std::os::raw::c_void, 14 | arg2: *mut ::std::os::raw::c_void, 15 | arg3: *mut ::std::os::raw::c_void, 16 | ) -> *mut CFlouiViewController; 17 | } 18 | extern "C" { 19 | pub fn CFlouiViewController_handle_events(arg1: *mut ::std::os::raw::c_void); 20 | } 21 | #[repr(C)] 22 | #[derive(Debug, Copy, Clone)] 23 | pub struct CWidget { 24 | _unused: [u8; 0], 25 | } 26 | extern "C" { 27 | pub fn CWidget_id(self_: *mut CWidget, id: *const ::std::os::raw::c_char); 28 | } 29 | extern "C" { 30 | pub fn CWidget_background(self_: *mut CWidget, col: ::std::os::raw::c_uint); 31 | } 32 | extern "C" { 33 | pub fn CWidget_size(self_: *mut CWidget, w: ::std::os::raw::c_int, h: ::std::os::raw::c_int); 34 | } 35 | extern "C" { 36 | pub fn CWidget_inner(self_: *mut CWidget) -> *mut ::std::os::raw::c_void; 37 | } 38 | pub type CFlouiCallback = ::std::option::Option< 39 | unsafe extern "C" fn(arg1: *mut CWidget, data: *mut ::std::os::raw::c_void), 40 | >; 41 | #[repr(C)] 42 | #[derive(Debug, Copy, Clone)] 43 | pub struct CMainView { 44 | _unused: [u8; 0], 45 | } 46 | extern "C" { 47 | pub fn CMainView_new(fvc: *const CFlouiViewController) -> *mut CMainView; 48 | } 49 | extern "C" { 50 | pub fn CMainView_id(self_: *mut CMainView, id: *const ::std::os::raw::c_char); 51 | } 52 | extern "C" { 53 | pub fn CMainView_background(self_: *mut CMainView, col: ::std::os::raw::c_uint); 54 | } 55 | extern "C" { 56 | pub fn CMainView_size( 57 | self_: *mut CMainView, 58 | w: ::std::os::raw::c_int, 59 | h: ::std::os::raw::c_int, 60 | ); 61 | } 62 | extern "C" { 63 | pub fn CMainView_inner(self_: *mut CMainView) -> *mut ::std::os::raw::c_void; 64 | } 65 | extern "C" { 66 | pub fn CMainView_add(self_: *mut CMainView, w: *const CWidget); 67 | } 68 | extern "C" { 69 | pub fn CMainView_remove(self_: *mut CMainView, w: *const CWidget); 70 | } 71 | extern "C" { 72 | pub fn CMainView_clear(self_: *mut CMainView); 73 | } 74 | extern "C" { 75 | pub fn CMainView_spacing(self_: *mut CMainView, spacing: ::std::os::raw::c_int); 76 | } 77 | #[repr(C)] 78 | #[derive(Debug, Copy, Clone)] 79 | pub struct CVStack { 80 | _unused: [u8; 0], 81 | } 82 | extern "C" { 83 | pub fn CVStack_new() -> *mut CVStack; 84 | } 85 | extern "C" { 86 | pub fn CVStack_id(self_: *mut CVStack, id: *const ::std::os::raw::c_char); 87 | } 88 | extern "C" { 89 | pub fn CVStack_background(self_: *mut CVStack, col: ::std::os::raw::c_uint); 90 | } 91 | extern "C" { 92 | pub fn CVStack_size(self_: *mut CVStack, w: ::std::os::raw::c_int, h: ::std::os::raw::c_int); 93 | } 94 | extern "C" { 95 | pub fn CVStack_inner(self_: *mut CVStack) -> *mut ::std::os::raw::c_void; 96 | } 97 | extern "C" { 98 | pub fn CVStack_add(self_: *mut CVStack, w: *const CWidget); 99 | } 100 | extern "C" { 101 | pub fn CVStack_remove(self_: *mut CVStack, w: *const CWidget); 102 | } 103 | extern "C" { 104 | pub fn CVStack_clear(self_: *mut CVStack); 105 | } 106 | extern "C" { 107 | pub fn CVStack_spacing(self_: *mut CVStack, spacing: ::std::os::raw::c_int); 108 | } 109 | #[repr(C)] 110 | #[derive(Debug, Copy, Clone)] 111 | pub struct CHStack { 112 | _unused: [u8; 0], 113 | } 114 | extern "C" { 115 | pub fn CHStack_new() -> *mut CHStack; 116 | } 117 | extern "C" { 118 | pub fn CHStack_id(self_: *mut CHStack, id: *const ::std::os::raw::c_char); 119 | } 120 | extern "C" { 121 | pub fn CHStack_background(self_: *mut CHStack, col: ::std::os::raw::c_uint); 122 | } 123 | extern "C" { 124 | pub fn CHStack_size(self_: *mut CHStack, w: ::std::os::raw::c_int, h: ::std::os::raw::c_int); 125 | } 126 | extern "C" { 127 | pub fn CHStack_inner(self_: *mut CHStack) -> *mut ::std::os::raw::c_void; 128 | } 129 | extern "C" { 130 | pub fn CHStack_add(self_: *mut CHStack, w: *const CWidget); 131 | } 132 | extern "C" { 133 | pub fn CHStack_remove(self_: *mut CHStack, w: *const CWidget); 134 | } 135 | extern "C" { 136 | pub fn CHStack_clear(self_: *mut CHStack); 137 | } 138 | extern "C" { 139 | pub fn CHStack_spacing(self_: *mut CHStack, spacing: ::std::os::raw::c_int); 140 | } 141 | #[repr(C)] 142 | #[derive(Debug, Copy, Clone)] 143 | pub struct CButton { 144 | _unused: [u8; 0], 145 | } 146 | extern "C" { 147 | pub fn CButton_id(self_: *mut CButton, id: *const ::std::os::raw::c_char); 148 | } 149 | extern "C" { 150 | pub fn CButton_background(self_: *mut CButton, col: ::std::os::raw::c_uint); 151 | } 152 | extern "C" { 153 | pub fn CButton_size(self_: *mut CButton, w: ::std::os::raw::c_int, h: ::std::os::raw::c_int); 154 | } 155 | extern "C" { 156 | pub fn CButton_inner(self_: *mut CButton) -> *mut ::std::os::raw::c_void; 157 | } 158 | extern "C" { 159 | pub fn CButton_new(label: *const ::std::os::raw::c_char) -> *mut CButton; 160 | } 161 | extern "C" { 162 | pub fn CButton_action( 163 | self_: *mut CButton, 164 | cb: CFlouiCallback, 165 | data: *mut ::std::os::raw::c_void, 166 | ); 167 | } 168 | extern "C" { 169 | pub fn CButton_filled(self_: *mut CButton); 170 | } 171 | extern "C" { 172 | pub fn CButton_foreground(self_: *mut CButton, c: ::std::os::raw::c_uint); 173 | } 174 | #[repr(C)] 175 | #[derive(Debug, Copy, Clone)] 176 | pub struct CToggle { 177 | _unused: [u8; 0], 178 | } 179 | extern "C" { 180 | pub fn CToggle_id(self_: *mut CToggle, id: *const ::std::os::raw::c_char); 181 | } 182 | extern "C" { 183 | pub fn CToggle_background(self_: *mut CToggle, col: ::std::os::raw::c_uint); 184 | } 185 | extern "C" { 186 | pub fn CToggle_size(self_: *mut CToggle, w: ::std::os::raw::c_int, h: ::std::os::raw::c_int); 187 | } 188 | extern "C" { 189 | pub fn CToggle_inner(self_: *mut CToggle) -> *mut ::std::os::raw::c_void; 190 | } 191 | extern "C" { 192 | pub fn CToggle_new(label: *const ::std::os::raw::c_char) -> *mut CToggle; 193 | } 194 | extern "C" { 195 | pub fn CToggle_action( 196 | self_: *mut CToggle, 197 | cb: CFlouiCallback, 198 | data: *mut ::std::os::raw::c_void, 199 | ); 200 | } 201 | extern "C" { 202 | pub fn CToggle_set_value(self_: *mut CToggle, val: ::std::os::raw::c_int); 203 | } 204 | extern "C" { 205 | pub fn CToggle_value(self_: *mut CToggle) -> ::std::os::raw::c_int; 206 | } 207 | extern "C" { 208 | pub fn CToggle_foreground(self_: *mut CToggle, c: ::std::os::raw::c_uint); 209 | } 210 | #[repr(C)] 211 | #[derive(Debug, Copy, Clone)] 212 | pub struct CCheck { 213 | _unused: [u8; 0], 214 | } 215 | extern "C" { 216 | pub fn CCheck_id(self_: *mut CCheck, id: *const ::std::os::raw::c_char); 217 | } 218 | extern "C" { 219 | pub fn CCheck_background(self_: *mut CCheck, col: ::std::os::raw::c_uint); 220 | } 221 | extern "C" { 222 | pub fn CCheck_size(self_: *mut CCheck, w: ::std::os::raw::c_int, h: ::std::os::raw::c_int); 223 | } 224 | extern "C" { 225 | pub fn CCheck_inner(self_: *mut CCheck) -> *mut ::std::os::raw::c_void; 226 | } 227 | extern "C" { 228 | pub fn CCheck_new(label: *const ::std::os::raw::c_char) -> *mut CCheck; 229 | } 230 | extern "C" { 231 | pub fn CCheck_action(self_: *mut CCheck, cb: CFlouiCallback, data: *mut ::std::os::raw::c_void); 232 | } 233 | extern "C" { 234 | pub fn CCheck_set_value(self_: *mut CCheck, val: ::std::os::raw::c_int); 235 | } 236 | extern "C" { 237 | pub fn CCheck_value(self_: *mut CCheck) -> ::std::os::raw::c_int; 238 | } 239 | extern "C" { 240 | pub fn CCheck_foreground(self_: *mut CCheck, c: ::std::os::raw::c_uint); 241 | } 242 | #[repr(C)] 243 | #[derive(Debug, Copy, Clone)] 244 | pub struct CSlider { 245 | _unused: [u8; 0], 246 | } 247 | extern "C" { 248 | pub fn CSlider_id(self_: *mut CSlider, id: *const ::std::os::raw::c_char); 249 | } 250 | extern "C" { 251 | pub fn CSlider_background(self_: *mut CSlider, col: ::std::os::raw::c_uint); 252 | } 253 | extern "C" { 254 | pub fn CSlider_size(self_: *mut CSlider, w: ::std::os::raw::c_int, h: ::std::os::raw::c_int); 255 | } 256 | extern "C" { 257 | pub fn CSlider_inner(self_: *mut CSlider) -> *mut ::std::os::raw::c_void; 258 | } 259 | extern "C" { 260 | pub fn CSlider_new() -> *mut CSlider; 261 | } 262 | extern "C" { 263 | pub fn CSlider_action( 264 | self_: *mut CSlider, 265 | cb: CFlouiCallback, 266 | data: *mut ::std::os::raw::c_void, 267 | ); 268 | } 269 | extern "C" { 270 | pub fn CSlider_set_value(self_: *mut CSlider, val: f64); 271 | } 272 | extern "C" { 273 | pub fn CSlider_value(self_: *mut CSlider) -> f64; 274 | } 275 | extern "C" { 276 | pub fn CSlider_foreground(self_: *mut CSlider, c: ::std::os::raw::c_uint); 277 | } 278 | #[repr(C)] 279 | #[derive(Debug, Copy, Clone)] 280 | pub struct CText { 281 | _unused: [u8; 0], 282 | } 283 | extern "C" { 284 | pub fn CText_id(self_: *mut CText, id: *const ::std::os::raw::c_char); 285 | } 286 | extern "C" { 287 | pub fn CText_background(self_: *mut CText, col: ::std::os::raw::c_uint); 288 | } 289 | extern "C" { 290 | pub fn CText_size(self_: *mut CText, w: ::std::os::raw::c_int, h: ::std::os::raw::c_int); 291 | } 292 | extern "C" { 293 | pub fn CText_inner(self_: *mut CText) -> *mut ::std::os::raw::c_void; 294 | } 295 | extern "C" { 296 | pub fn CText_new(label: *const ::std::os::raw::c_char) -> *mut CText; 297 | } 298 | extern "C" { 299 | pub fn CText_text(self_: *mut CText, t: *const ::std::os::raw::c_char); 300 | } 301 | extern "C" { 302 | pub fn CText_center(self_: *mut CText); 303 | } 304 | extern "C" { 305 | pub fn CText_left(self_: *mut CText); 306 | } 307 | extern "C" { 308 | pub fn CText_right(self_: *mut CText); 309 | } 310 | extern "C" { 311 | pub fn CText_bold(self_: *mut CText); 312 | } 313 | extern "C" { 314 | pub fn CText_italic(self_: *mut CText); 315 | } 316 | extern "C" { 317 | pub fn CText_normal(self_: *mut CText); 318 | } 319 | extern "C" { 320 | pub fn CText_foreground(self_: *mut CText, c: ::std::os::raw::c_uint); 321 | } 322 | extern "C" { 323 | pub fn CText_fontsize(self_: *mut CText, size: ::std::os::raw::c_int); 324 | } 325 | #[repr(C)] 326 | #[derive(Debug, Copy, Clone)] 327 | pub struct CTextField { 328 | _unused: [u8; 0], 329 | } 330 | extern "C" { 331 | pub fn CTextField_id(self_: *mut CTextField, id: *const ::std::os::raw::c_char); 332 | } 333 | extern "C" { 334 | pub fn CTextField_background(self_: *mut CTextField, col: ::std::os::raw::c_uint); 335 | } 336 | extern "C" { 337 | pub fn CTextField_size( 338 | self_: *mut CTextField, 339 | w: ::std::os::raw::c_int, 340 | h: ::std::os::raw::c_int, 341 | ); 342 | } 343 | extern "C" { 344 | pub fn CTextField_inner(self_: *mut CTextField) -> *mut ::std::os::raw::c_void; 345 | } 346 | extern "C" { 347 | pub fn CTextField_new() -> *mut CTextField; 348 | } 349 | extern "C" { 350 | pub fn CTextField_text(self_: *mut CTextField, t: *const ::std::os::raw::c_char); 351 | } 352 | extern "C" { 353 | pub fn CTextField_center(self_: *mut CTextField); 354 | } 355 | extern "C" { 356 | pub fn CTextField_left(self_: *mut CTextField); 357 | } 358 | extern "C" { 359 | pub fn CTextField_right(self_: *mut CTextField); 360 | } 361 | extern "C" { 362 | pub fn CTextField_foreground(self_: *mut CTextField, c: ::std::os::raw::c_uint); 363 | } 364 | extern "C" { 365 | pub fn CTextField_fontsize(self_: *mut CTextField, size: ::std::os::raw::c_int); 366 | } 367 | #[repr(C)] 368 | #[derive(Debug, Copy, Clone)] 369 | pub struct CSpacer { 370 | _unused: [u8; 0], 371 | } 372 | extern "C" { 373 | pub fn CSpacer_id(self_: *mut CSpacer, id: *const ::std::os::raw::c_char); 374 | } 375 | extern "C" { 376 | pub fn CSpacer_background(self_: *mut CSpacer, col: ::std::os::raw::c_uint); 377 | } 378 | extern "C" { 379 | pub fn CSpacer_size(self_: *mut CSpacer, w: ::std::os::raw::c_int, h: ::std::os::raw::c_int); 380 | } 381 | extern "C" { 382 | pub fn CSpacer_inner(self_: *mut CSpacer) -> *mut ::std::os::raw::c_void; 383 | } 384 | extern "C" { 385 | pub fn CSpacer_new() -> *mut CSpacer; 386 | } 387 | #[repr(C)] 388 | #[derive(Debug, Copy, Clone)] 389 | pub struct CImageView { 390 | _unused: [u8; 0], 391 | } 392 | extern "C" { 393 | pub fn CImageView_id(self_: *mut CImageView, id: *const ::std::os::raw::c_char); 394 | } 395 | extern "C" { 396 | pub fn CImageView_background(self_: *mut CImageView, col: ::std::os::raw::c_uint); 397 | } 398 | extern "C" { 399 | pub fn CImageView_size( 400 | self_: *mut CImageView, 401 | w: ::std::os::raw::c_int, 402 | h: ::std::os::raw::c_int, 403 | ); 404 | } 405 | extern "C" { 406 | pub fn CImageView_inner(self_: *mut CImageView) -> *mut ::std::os::raw::c_void; 407 | } 408 | extern "C" { 409 | pub fn CImageView_new() -> *mut CImageView; 410 | } 411 | extern "C" { 412 | pub fn CImageView_load(path: *const ::std::os::raw::c_char) -> *mut CImageView; 413 | } 414 | extern "C" { 415 | pub fn CImageView_image(self_: *mut CImageView, path: *const ::std::os::raw::c_char); 416 | } 417 | #[repr(C)] 418 | #[derive(Debug, Copy, Clone)] 419 | pub struct CWebView { 420 | _unused: [u8; 0], 421 | } 422 | extern "C" { 423 | pub fn CWebView_id(self_: *mut CWebView, id: *const ::std::os::raw::c_char); 424 | } 425 | extern "C" { 426 | pub fn CWebView_background(self_: *mut CWebView, col: ::std::os::raw::c_uint); 427 | } 428 | extern "C" { 429 | pub fn CWebView_size(self_: *mut CWebView, w: ::std::os::raw::c_int, h: ::std::os::raw::c_int); 430 | } 431 | extern "C" { 432 | pub fn CWebView_inner(self_: *mut CWebView) -> *mut ::std::os::raw::c_void; 433 | } 434 | extern "C" { 435 | pub fn CWebView_new() -> *mut CWebView; 436 | } 437 | extern "C" { 438 | pub fn CWebView_load_url(self_: *mut CWebView, url: *const ::std::os::raw::c_char); 439 | } 440 | extern "C" { 441 | pub fn CWebView_load_html(self_: *mut CWebView, html: *const ::std::os::raw::c_char); 442 | } 443 | #[repr(C)] 444 | #[derive(Debug, Copy, Clone)] 445 | pub struct CScrollView { 446 | _unused: [u8; 0], 447 | } 448 | extern "C" { 449 | pub fn CScrollView_id(self_: *mut CScrollView, id: *const ::std::os::raw::c_char); 450 | } 451 | extern "C" { 452 | pub fn CScrollView_background(self_: *mut CScrollView, col: ::std::os::raw::c_uint); 453 | } 454 | extern "C" { 455 | pub fn CScrollView_size( 456 | self_: *mut CScrollView, 457 | w: ::std::os::raw::c_int, 458 | h: ::std::os::raw::c_int, 459 | ); 460 | } 461 | extern "C" { 462 | pub fn CScrollView_inner(self_: *mut CScrollView) -> *mut ::std::os::raw::c_void; 463 | } 464 | extern "C" { 465 | pub fn CScrollView_new(w: *const CWidget) -> *mut CScrollView; 466 | } 467 | -------------------------------------------------------------------------------- /floui-sys/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod floui; 2 | pub use floui::*; -------------------------------------------------------------------------------- /src/enums.rs: -------------------------------------------------------------------------------- 1 | #![allow(non_upper_case_globals)] 2 | 3 | /// Wraps an RGBA color 4 | pub struct Color(pub u32); 5 | 6 | impl Color { 7 | pub const IndianRed: Color = Color::rgb(205, 92, 92); 8 | pub const LightCoral: Color = Color::rgb(240, 128, 128); 9 | pub const Salmon: Color = Color::rgb(250, 128, 114); 10 | pub const DarkSalmon: Color = Color::rgb(233, 150, 122); 11 | pub const LightSalmon: Color = Color::rgb(255, 160, 122); 12 | pub const Crimson: Color = Color::rgb(220, 20, 60); 13 | pub const Red: Color = Color::rgb(255, 0, 0); 14 | pub const FireBrick: Color = Color::rgb(178, 34, 34); 15 | pub const DarkRed: Color = Color::rgb(139, 0, 0); 16 | pub const Pink: Color = Color::rgb(255, 192, 203); 17 | pub const LightPink: Color = Color::rgb(255, 182, 193); 18 | pub const HotPink: Color = Color::rgb(255, 105, 180); 19 | pub const DeepPink: Color = Color::rgb(255, 20, 147); 20 | pub const MediumVioletRed: Color = Color::rgb(199, 21, 133); 21 | pub const PaleVioletRed: Color = Color::rgb(219, 112, 147); 22 | pub const Coral: Color = Color::rgb(255, 127, 80); 23 | pub const Tomato: Color = Color::rgb(255, 99, 71); 24 | pub const OrangeRed: Color = Color::rgb(255, 69, 0); 25 | pub const DarkOrange: Color = Color::rgb(255, 140, 0); 26 | pub const Orange: Color = Color::rgb(255, 165, 0); 27 | pub const Gold: Color = Color::rgb(255, 215, 0); 28 | pub const Yellow: Color = Color::rgb(255, 255, 0); 29 | pub const LightYellow: Color = Color::rgb(255, 255, 224); 30 | pub const LemonChiffon: Color = Color::rgb(255, 250, 205); 31 | pub const LightGoldenrodYellow: Color = Color::rgb(250, 250, 210); 32 | pub const PapayaWhip: Color = Color::rgb(255, 239, 213); 33 | pub const Moccasin: Color = Color::rgb(255, 228, 181); 34 | pub const PeachPuff: Color = Color::rgb(255, 218, 185); 35 | pub const PaleGoldenrod: Color = Color::rgb(238, 232, 170); 36 | pub const Khaki: Color = Color::rgb(240, 230, 140); 37 | pub const DarkKhaki: Color = Color::rgb(189, 183, 107); 38 | pub const Lavender: Color = Color::rgb(230, 230, 250); 39 | pub const Thistle: Color = Color::rgb(216, 191, 216); 40 | pub const Plum: Color = Color::rgb(221, 160, 221); 41 | pub const Violet: Color = Color::rgb(238, 130, 238); 42 | pub const Orchid: Color = Color::rgb(218, 112, 214); 43 | pub const Fuchsia: Color = Color::rgb(255, 0, 255); 44 | pub const Magenta: Color = Color::rgb(255, 0, 255); 45 | pub const MediumOrchid: Color = Color::rgb(186, 85, 211); 46 | pub const MediumPurple: Color = Color::rgb(147, 112, 219); 47 | pub const RebeccaPurple: Color = Color::rgb(102, 51, 153); 48 | pub const BlueViolet: Color = Color::rgb(138, 43, 226); 49 | pub const DarkViolet: Color = Color::rgb(148, 0, 211); 50 | pub const DarkOrchid: Color = Color::rgb(153, 50, 204); 51 | pub const DarkMagenta: Color = Color::rgb(139, 0, 139); 52 | pub const Purple: Color = Color::rgb(128, 0, 128); 53 | pub const Indigo: Color = Color::rgb(75, 0, 130); 54 | pub const SlateBlue: Color = Color::rgb(106, 90, 205); 55 | pub const DarkSlateBlue: Color = Color::rgb(72, 61, 139); 56 | pub const MediumSlateBlue: Color = Color::rgb(123, 104, 238); 57 | pub const GreenYellow: Color = Color::rgb(173, 255, 47); 58 | pub const Chartreuse: Color = Color::rgb(127, 255, 0); 59 | pub const LawnGreen: Color = Color::rgb(124, 252, 0); 60 | pub const Lime: Color = Color::rgb(0, 255, 0); 61 | pub const LimeGreen: Color = Color::rgb(50, 205, 50); 62 | pub const PaleGreen: Color = Color::rgb(152, 251, 152); 63 | pub const LightGreen: Color = Color::rgb(144, 238, 144); 64 | pub const MediumSpringGreen: Color = Color::rgb(0, 250, 154); 65 | pub const SpringGreen: Color = Color::rgb(0, 255, 127); 66 | pub const MediumSeaGreen: Color = Color::rgb(60, 179, 113); 67 | pub const SeaGreen: Color = Color::rgb(46, 139, 87); 68 | pub const ForestGreen: Color = Color::rgb(34, 139, 34); 69 | pub const Green: Color = Color::rgb(0, 128, 0); 70 | pub const DarkGreen: Color = Color::rgb(0, 100, 0); 71 | pub const YellowGreen: Color = Color::rgb(154, 205, 50); 72 | pub const OliveDrab: Color = Color::rgb(107, 142, 35); 73 | pub const Olive: Color = Color::rgb(128, 128, 0); 74 | pub const DarkOliveGreen: Color = Color::rgb(85, 107, 47); 75 | pub const MediumAquamarine: Color = Color::rgb(102, 205, 170); 76 | pub const DarkSeaGreen: Color = Color::rgb(143, 188, 139); 77 | pub const LightSeaGreen: Color = Color::rgb(32, 178, 170); 78 | pub const DarkCyan: Color = Color::rgb(0, 139, 139); 79 | pub const Teal: Color = Color::rgb(0, 128, 128); 80 | pub const Aqua: Color = Color::rgb(0, 255, 255); 81 | pub const Cyan: Color = Color::rgb(0, 255, 255); 82 | pub const LightCyan: Color = Color::rgb(224, 255, 255); 83 | pub const PaleTurquoise: Color = Color::rgb(175, 238, 238); 84 | pub const Aquamarine: Color = Color::rgb(127, 255, 212); 85 | pub const Turquoise: Color = Color::rgb(64, 224, 208); 86 | pub const MediumTurquoise: Color = Color::rgb(72, 209, 204); 87 | pub const DarkTurquoise: Color = Color::rgb(0, 206, 209); 88 | pub const CadetBlue: Color = Color::rgb(95, 158, 160); 89 | pub const SteelBlue: Color = Color::rgb(70, 130, 180); 90 | pub const LightSteelBlue: Color = Color::rgb(176, 196, 222); 91 | pub const PowderBlue: Color = Color::rgb(176, 224, 230); 92 | pub const LightBlue: Color = Color::rgb(173, 216, 230); 93 | pub const SkyBlue: Color = Color::rgb(135, 206, 235); 94 | pub const LightSkyBlue: Color = Color::rgb(135, 206, 250); 95 | pub const DeepSkyBlue: Color = Color::rgb(0, 191, 255); 96 | pub const DodgerBlue: Color = Color::rgb(30, 144, 255); 97 | pub const CornflowerBlue: Color = Color::rgb(100, 149, 237); 98 | pub const RoyalBlue: Color = Color::rgb(65, 105, 225); 99 | pub const Blue: Color = Color::rgb(0, 0, 255); 100 | pub const MediumBlue: Color = Color::rgb(0, 0, 205); 101 | pub const DarkBlue: Color = Color::rgb(0, 0, 139); 102 | pub const Navy: Color = Color::rgb(0, 0, 128); 103 | pub const MidnightBlue: Color = Color::rgb(25, 25, 112); 104 | pub const Cornsilk: Color = Color::rgb(255, 248, 220); 105 | pub const BlanchedAlmond: Color = Color::rgb(255, 235, 205); 106 | pub const Bisque: Color = Color::rgb(255, 228, 196); 107 | pub const NavajoWhite: Color = Color::rgb(255, 222, 173); 108 | pub const Wheat: Color = Color::rgb(245, 222, 179); 109 | pub const BurlyWood: Color = Color::rgb(222, 184, 135); 110 | pub const Tan: Color = Color::rgb(210, 180, 140); 111 | pub const RosyBrown: Color = Color::rgb(188, 143, 143); 112 | pub const SandyBrown: Color = Color::rgb(244, 164, 96); 113 | pub const Goldenrod: Color = Color::rgb(218, 165, 32); 114 | pub const DarkGoldenrod: Color = Color::rgb(184, 134, 11); 115 | pub const Peru: Color = Color::rgb(205, 133, 63); 116 | pub const Chocolate: Color = Color::rgb(210, 105, 30); 117 | pub const SaddleBrown: Color = Color::rgb(139, 69, 19); 118 | pub const Sienna: Color = Color::rgb(160, 82, 45); 119 | pub const Brown: Color = Color::rgb(165, 42, 42); 120 | pub const Maroon: Color = Color::rgb(128, 0, 0); 121 | pub const White: Color = Color::rgb(255, 255, 255); 122 | pub const Snow: Color = Color::rgb(255, 250, 250); 123 | pub const HoneyDew: Color = Color::rgb(240, 255, 240); 124 | pub const MintCream: Color = Color::rgb(245, 255, 250); 125 | pub const Azure: Color = Color::rgb(240, 255, 255); 126 | pub const AliceBlue: Color = Color::rgb(240, 248, 255); 127 | pub const GhostWhite: Color = Color::rgb(248, 248, 255); 128 | pub const WhiteSmoke: Color = Color::rgb(245, 245, 245); 129 | pub const SeaShell: Color = Color::rgb(255, 245, 238); 130 | pub const Beige: Color = Color::rgb(245, 245, 220); 131 | pub const OldLace: Color = Color::rgb(253, 245, 230); 132 | pub const FloralWhite: Color = Color::rgb(255, 250, 240); 133 | pub const Ivory: Color = Color::rgb(255, 255, 240); 134 | pub const AntiqueWhite: Color = Color::rgb(250, 235, 215); 135 | pub const Linen: Color = Color::rgb(250, 240, 230); 136 | pub const LavenderBlush: Color = Color::rgb(255, 240, 245); 137 | pub const MistyRose: Color = Color::rgb(255, 228, 225); 138 | pub const Gainsboro: Color = Color::rgb(220, 220, 220); 139 | pub const LightGray: Color = Color::rgb(211, 211, 211); 140 | pub const Silver: Color = Color::rgb(192, 192, 192); 141 | pub const DarkGray: Color = Color::rgb(169, 169, 169); 142 | pub const Gray: Color = Color::rgb(128, 128, 128); 143 | pub const DimGray: Color = Color::rgb(105, 105, 105); 144 | pub const LightSlateGray: Color = Color::rgb(119, 136, 153); 145 | pub const SlateGray: Color = Color::rgb(112, 128, 144); 146 | pub const DarkSlateGray: Color = Color::rgb(47, 79, 79); 147 | pub const Black: Color = Color::rgb(0, 0, 0); 148 | /// Constructs a color from rgb values 149 | pub const fn rgb(r: u8, g: u8, b: u8) -> Color { 150 | Color::rgba(r, g, b, 255) 151 | } 152 | /// Constructs a color from rgba values 153 | pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Color { 154 | Color( 155 | ((r as u32 & 0xff) << 24) 156 | + ((g as u32 & 0xff) << 16) 157 | + ((b as u32 & 0xff) << 8) 158 | + (a as u32 & 0xff), 159 | ) 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::needless_doctest_main)] 2 | // #![warn(missing_docs)] 3 | 4 | /// Imports log and the WidgetExt trait 5 | pub mod prelude; 6 | 7 | /// Import Color...etc 8 | pub mod enums; 9 | 10 | /// Imports widgets 11 | pub mod widgets; 12 | -------------------------------------------------------------------------------- /src/prelude.rs: -------------------------------------------------------------------------------- 1 | use std::any::Any; 2 | use std::collections::HashMap; 3 | use std::os::raw::c_void; 4 | use std::sync::Arc; 5 | use std::sync::Mutex; 6 | 7 | use crate::enums::Color; 8 | 9 | lazy_static::lazy_static! { 10 | static ref WIDGET_MAP: Mutex>> = Mutex::new(HashMap::default()); 11 | } 12 | 13 | /// Print to console 14 | pub fn log(s: &str) { 15 | let s = std::ffi::CString::new(s).unwrap(); 16 | unsafe { 17 | floui_sys::Cfloui_log(s.as_ptr()); 18 | } 19 | } 20 | 21 | /// Obtain a specific widget from an id 22 | /// ```rust,no_run 23 | /// use floui::widgets::Text; 24 | /// use floui::prelude::from_id; 25 | /// let t: Text = from_id("mytext").unwrap(); 26 | /// ``` 27 | pub fn from_id(id: &str) -> Option { 28 | if let Some(w) = WIDGET_MAP.lock().unwrap().get(&id) { 29 | if let Some(t) = w.downcast_ref::() { 30 | Some(t.clone()) 31 | } else { 32 | None 33 | } 34 | } else { 35 | None 36 | } 37 | } 38 | 39 | /// Traits implemented by all widgets 40 | pub unsafe trait WidgetExt { 41 | /// Gets the inner wrapper 42 | fn inner(&self) -> *mut floui_sys::CWidget; 43 | /// Gets the underlying pointer (JNI jobject on android, UIView on iOS) 44 | fn underlying(&self) -> *mut c_void { 45 | unsafe { floui_sys::CWidget_inner(&mut *self.inner() as _) } 46 | } 47 | /// Constructs a new widget from a widget pointer 48 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self 49 | where 50 | Self: Sized; 51 | /// Adds the widget to the widget map, and assigns it an id 52 | fn id(self, id: &'static str) -> Self 53 | where 54 | Self: 'static + Sync + Sized + Clone + Send, 55 | { 56 | WIDGET_MAP 57 | .lock() 58 | .unwrap() 59 | .insert(id, Box::new(self.clone())); 60 | self 61 | } 62 | /// Sets the background color 63 | fn background(self, col: Color) -> Self 64 | where 65 | Self: Sized, 66 | { 67 | unsafe { floui_sys::CWidget_background(self.inner(), col.0) } 68 | self 69 | } 70 | } 71 | 72 | /// The view controller struct 73 | #[derive(Clone)] 74 | pub struct ViewController { 75 | pub(crate) inner: Arc<*mut floui_sys::CFlouiViewController>, 76 | } 77 | 78 | impl ViewController { 79 | /// On Android, arg1: JNIEnv, arg2: main view, arg3: ConstraintLayout 80 | pub unsafe fn new(arg1: *mut c_void, arg2: *mut c_void, arg3: *mut c_void) -> Self { 81 | let inner = Arc::new(floui_sys::CFlouiViewController_new(arg1, arg2, arg3)); 82 | Self { inner } 83 | } 84 | /// Required on android 85 | pub unsafe fn handle_events(view: *mut c_void) { 86 | floui_sys::CFlouiViewController_handle_events(view); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/widgets/button.rs: -------------------------------------------------------------------------------- 1 | use crate::{enums, prelude::*}; 2 | use floui_sys; 3 | use std::sync::Arc; 4 | 5 | /// A Button widget 6 | #[derive(Clone)] 7 | pub struct Button { 8 | inner: Arc<*mut floui_sys::CButton>, 9 | } 10 | 11 | unsafe impl Sync for Button {} 12 | unsafe impl Send for Button {} 13 | 14 | unsafe impl WidgetExt for Button { 15 | fn inner(&self) -> *mut floui_sys::CWidget { 16 | *self.inner as _ 17 | } 18 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 19 | Self { 20 | inner: Arc::new(ptr as _), 21 | } 22 | } 23 | } 24 | 25 | impl Button { 26 | /// Constructs a new widget 27 | pub fn new(label: &str) -> Self { 28 | let label = std::ffi::CString::new(label).unwrap(); 29 | let inner = unsafe { Arc::new(floui_sys::CButton_new(label.as_ptr())) }; 30 | Self { inner } 31 | } 32 | 33 | /// Sets the action of the widget 34 | pub fn action(self, cb: F) -> Self { 35 | unsafe { 36 | unsafe extern "C" fn shim( 37 | wid: *mut floui_sys::CWidget, 38 | data: *mut std::os::raw::c_void, 39 | ) { 40 | let wid = Button::from_widget_ptr(wid as *mut _); 41 | let a = data as *mut Box; 42 | let f: &mut (dyn FnMut(&Button)) = &mut **a; 43 | let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&wid))); 44 | } 45 | let a: *mut Box = Box::into_raw(Box::new(Box::new(cb))); 46 | let data: *mut std::os::raw::c_void = a as *mut std::os::raw::c_void; 47 | let callback: floui_sys::CFlouiCallback = Some(shim); 48 | floui_sys::CButton_action(*self.inner, callback, data); 49 | } 50 | self 51 | } 52 | 53 | /// Set the button to be filled 54 | pub fn filled(self) -> Self { 55 | unsafe { floui_sys::CButton_filled(*self.inner) } 56 | self 57 | } 58 | 59 | /// Sets the foreground color 60 | pub fn foreground(self, col: enums::Color) -> Self { 61 | unsafe { floui_sys::CButton_foreground(*self.inner, col.0) } 62 | self 63 | } 64 | } 65 | 66 | /// A Toggle widget 67 | #[derive(Clone)] 68 | pub struct Toggle { 69 | inner: Arc<*mut floui_sys::CToggle>, 70 | } 71 | 72 | unsafe impl Sync for Toggle {} 73 | unsafe impl Send for Toggle {} 74 | 75 | unsafe impl WidgetExt for Toggle { 76 | fn inner(&self) -> *mut floui_sys::CWidget { 77 | *self.inner as _ 78 | } 79 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 80 | Self { 81 | inner: Arc::new(ptr as _), 82 | } 83 | } 84 | } 85 | 86 | impl Toggle { 87 | /// Constructs a new widget 88 | pub fn new(label: &str) -> Self { 89 | let label = std::ffi::CString::new(label).unwrap(); 90 | let inner = unsafe { Arc::new(floui_sys::CToggle_new(label.as_ptr())) }; 91 | Self { inner } 92 | } 93 | 94 | /// Sets the action of the widget 95 | pub fn action(self, cb: F) -> Self { 96 | unsafe { 97 | unsafe extern "C" fn shim( 98 | wid: *mut floui_sys::CWidget, 99 | data: *mut std::os::raw::c_void, 100 | ) { 101 | let wid = Toggle::from_widget_ptr(wid as *mut _); 102 | let a = data as *mut Box; 103 | let f: &mut (dyn FnMut(&Toggle)) = &mut **a; 104 | let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&wid))); 105 | } 106 | let a: *mut Box = Box::into_raw(Box::new(Box::new(cb))); 107 | let data: *mut std::os::raw::c_void = a as *mut std::os::raw::c_void; 108 | let callback: floui_sys::CFlouiCallback = Some(shim); 109 | floui_sys::CToggle_action(*self.inner, callback, data); 110 | } 111 | self 112 | } 113 | 114 | /// Sets the foreground color 115 | pub fn foreground(self, col: enums::Color) -> Self { 116 | unsafe { floui_sys::CToggle_foreground(*self.inner, col.0) } 117 | self 118 | } 119 | 120 | /// Sets whether the Toggle is set 121 | pub fn set_value(&self, val: bool) { 122 | unsafe { floui_sys::CToggle_set_value(*self.inner, val as i32) } 123 | } 124 | 125 | /// Constructs a toggle that is set depending on val 126 | pub fn with_value(self, val: bool) -> Self { 127 | self.set_value(val); 128 | self 129 | } 130 | 131 | /// Returs whether the toggle is set 132 | pub fn value(&self) -> bool { 133 | unsafe { floui_sys::CToggle_value(*self.inner) != 0 } 134 | } 135 | } 136 | 137 | /// A checkbox widget 138 | #[derive(Clone)] 139 | pub struct Check { 140 | inner: Arc<*mut floui_sys::CCheck>, 141 | } 142 | 143 | unsafe impl Sync for Check {} 144 | unsafe impl Send for Check {} 145 | 146 | unsafe impl WidgetExt for Check { 147 | fn inner(&self) -> *mut floui_sys::CWidget { 148 | *self.inner as _ 149 | } 150 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 151 | Self { 152 | inner: Arc::new(ptr as _), 153 | } 154 | } 155 | } 156 | 157 | impl Check { 158 | /// Constructs a new widget 159 | pub fn new(label: &str) -> Self { 160 | let label = std::ffi::CString::new(label).unwrap(); 161 | let inner = unsafe { Arc::new(floui_sys::CCheck_new(label.as_ptr())) }; 162 | Self { inner } 163 | } 164 | 165 | /// Sets the action of the widget 166 | pub fn action(self, cb: F) -> Self { 167 | unsafe { 168 | unsafe extern "C" fn shim( 169 | wid: *mut floui_sys::CWidget, 170 | data: *mut std::os::raw::c_void, 171 | ) { 172 | let wid = Check::from_widget_ptr(wid as *mut _); 173 | let a = data as *mut Box; 174 | let f: &mut (dyn FnMut(&Check)) = &mut **a; 175 | let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&wid))); 176 | } 177 | let a: *mut Box = Box::into_raw(Box::new(Box::new(cb))); 178 | let data: *mut std::os::raw::c_void = a as *mut std::os::raw::c_void; 179 | let callback: floui_sys::CFlouiCallback = Some(shim); 180 | floui_sys::CCheck_action(*self.inner, callback, data); 181 | } 182 | self 183 | } 184 | 185 | /// Sets the foreground color 186 | pub fn foreground(self, col: enums::Color) -> Self { 187 | unsafe { floui_sys::CCheck_foreground(*self.inner, col.0) } 188 | self 189 | } 190 | 191 | /// Sets whether the Check is set 192 | pub fn set_value(&self, val: bool) { 193 | unsafe { floui_sys::CCheck_set_value(*self.inner, val as i32) } 194 | } 195 | 196 | /// Constructs a check that is set depending on val 197 | pub fn with_value(self, val: bool) -> Self { 198 | self.set_value(val); 199 | self 200 | } 201 | 202 | /// Returs whether the check is set 203 | pub fn value(&self) -> bool { 204 | unsafe { floui_sys::CCheck_value(*self.inner) != 0 } 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /src/widgets/misc.rs: -------------------------------------------------------------------------------- 1 | use crate::{enums, prelude::*}; 2 | use floui_sys; 3 | use std::path::Path; 4 | use std::sync::Arc; 5 | 6 | /// A Spacer widget 7 | #[derive(Clone)] 8 | pub struct Spacer { 9 | inner: Arc<*mut floui_sys::CSpacer>, 10 | } 11 | 12 | unsafe impl Sync for Spacer {} 13 | unsafe impl Send for Spacer {} 14 | 15 | unsafe impl WidgetExt for Spacer { 16 | fn inner(&self) -> *mut floui_sys::CWidget { 17 | *self.inner as _ 18 | } 19 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 20 | Self { 21 | inner: Arc::new(ptr as _), 22 | } 23 | } 24 | } 25 | 26 | impl Spacer { 27 | /// Constructs a new widget 28 | pub fn new() -> Self { 29 | let inner = unsafe { Arc::new(floui_sys::CSpacer_new()) }; 30 | Self { inner } 31 | } 32 | } 33 | 34 | /// A ScrollView widget 35 | #[derive(Clone)] 36 | pub struct ScrollView { 37 | inner: Arc<*mut floui_sys::CScrollView>, 38 | } 39 | 40 | unsafe impl Sync for ScrollView {} 41 | unsafe impl Send for ScrollView {} 42 | 43 | unsafe impl WidgetExt for ScrollView { 44 | fn inner(&self) -> *mut floui_sys::CWidget { 45 | *self.inner as _ 46 | } 47 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 48 | Self { 49 | inner: Arc::new(ptr as _), 50 | } 51 | } 52 | } 53 | 54 | impl ScrollView { 55 | /// Constructs a new widget, Takes only a single widget 56 | pub fn new(widget: &impl WidgetExt) -> Self { 57 | let inner = unsafe { Arc::new(floui_sys::CScrollView_new(widget.inner())) }; 58 | Self { inner } 59 | } 60 | } 61 | 62 | /// A Slider widget 63 | #[derive(Clone)] 64 | pub struct Slider { 65 | inner: Arc<*mut floui_sys::CSlider>, 66 | } 67 | 68 | unsafe impl Sync for Slider {} 69 | unsafe impl Send for Slider {} 70 | 71 | unsafe impl WidgetExt for Slider { 72 | fn inner(&self) -> *mut floui_sys::CWidget { 73 | *self.inner as _ 74 | } 75 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 76 | Self { 77 | inner: Arc::new(ptr as _), 78 | } 79 | } 80 | } 81 | 82 | impl Slider { 83 | /// Constructs a new widget 84 | pub fn new() -> Self { 85 | let inner = unsafe { Arc::new(floui_sys::CSlider_new()) }; 86 | Self { inner } 87 | } 88 | 89 | /// Sets the action on changing the slider 90 | pub fn action(self, cb: F) -> Self { 91 | unsafe { 92 | unsafe extern "C" fn shim( 93 | wid: *mut floui_sys::CWidget, 94 | data: *mut std::os::raw::c_void, 95 | ) { 96 | let wid = Slider::from_widget_ptr(wid as *mut _); 97 | let a = data as *mut Box; 98 | let f: &mut (dyn FnMut(&Slider)) = &mut **a; 99 | let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| f(&wid))); 100 | } 101 | let a: *mut Box = Box::into_raw(Box::new(Box::new(cb))); 102 | let data: *mut std::os::raw::c_void = a as *mut std::os::raw::c_void; 103 | let callback: floui_sys::CFlouiCallback = Some(shim); 104 | floui_sys::CSlider_action(*self.inner, callback, data); 105 | } 106 | self 107 | } 108 | 109 | /// Sets the foreground color 110 | pub fn foreground(self, col: enums::Color) -> Self { 111 | unsafe { floui_sys::CSlider_foreground(*self.inner, col.0) } 112 | self 113 | } 114 | 115 | /// Sets the value of the slider 116 | pub fn set_value(&self, val: f64) { 117 | unsafe { floui_sys::CSlider_set_value(*self.inner, val) } 118 | } 119 | 120 | /// Constructs a slider with a value val 121 | pub fn with_value(self, val: f64) -> Self { 122 | self.set_value(val); 123 | self 124 | } 125 | 126 | /// Gets the slider's value 127 | pub fn value(&self) -> f64 { 128 | unsafe { floui_sys::CSlider_value(*self.inner) } 129 | } 130 | } 131 | 132 | /// A ImageView widget 133 | #[derive(Clone)] 134 | pub struct ImageView { 135 | inner: Arc<*mut floui_sys::CImageView>, 136 | } 137 | 138 | unsafe impl Sync for ImageView {} 139 | unsafe impl Send for ImageView {} 140 | 141 | unsafe impl WidgetExt for ImageView { 142 | fn inner(&self) -> *mut floui_sys::CWidget { 143 | *self.inner as _ 144 | } 145 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 146 | Self { 147 | inner: Arc::new(ptr as _), 148 | } 149 | } 150 | } 151 | 152 | impl ImageView { 153 | /// Constructs a new widget 154 | pub fn new() -> Self { 155 | let inner = unsafe { Arc::new(floui_sys::CImageView_new()) }; 156 | Self { inner } 157 | } 158 | 159 | /// Constructs an ImageView from an available image. Images should be in your platform's assets folder: 160 | /// On android: images need to be added to res/drawable. 161 | /// On iOS: images need to be added to Assets.xcassets 162 | pub fn load>(path: &P) -> Self { 163 | let path = std::ffi::CString::new(path.as_ref().to_str().unwrap()).unwrap(); 164 | let inner = unsafe { Arc::new(floui_sys::CImageView_load(path.as_ptr())) }; 165 | Self { inner } 166 | } 167 | 168 | /// Sets the image for the ImageView 169 | pub fn image>(self, path: &P) -> Self { 170 | let path = std::ffi::CString::new(path.as_ref().to_str().unwrap()).unwrap(); 171 | unsafe { 172 | floui_sys::CImageView_image(*self.inner, path.as_ptr()); 173 | } 174 | self 175 | } 176 | } 177 | 178 | /// A WebView widget 179 | #[derive(Clone)] 180 | pub struct WebView { 181 | inner: Arc<*mut floui_sys::CWebView>, 182 | } 183 | 184 | unsafe impl Sync for WebView {} 185 | unsafe impl Send for WebView {} 186 | 187 | unsafe impl WidgetExt for WebView { 188 | fn inner(&self) -> *mut floui_sys::CWidget { 189 | *self.inner as _ 190 | } 191 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 192 | Self { 193 | inner: Arc::new(ptr as _), 194 | } 195 | } 196 | } 197 | 198 | impl WebView { 199 | /// Constructs a new widget 200 | pub fn new() -> Self { 201 | let inner = unsafe { Arc::new(floui_sys::CWebView_new()) }; 202 | Self { inner } 203 | } 204 | 205 | /// Load a url. 206 | /// - on iOS: 207 | /// - Requires adding WebKit.framework under General > Frameworks, Libraries and Embedded Content. 208 | /// - Requires enabling the `ios-webview` flag in your Cargo.toml. 209 | /// - Local files can be loaded using WebView::load_url() but need to be preceded by `file:///`, the files should be added to your xcode project. 210 | /// - On Android: 211 | /// - To load local files, precede them with `file:///` and the path of the file, which should be added to an assets folder (File > New > Folder > Assets folder). This then can be loaded using WebView::load_url(). 212 | /// - To load http requests, you need to enable the internet permission in your AndroidManifest.xml: `` 213 | pub fn load_url>(self, path: &P) -> Self { 214 | let path = std::ffi::CString::new(path.as_ref().to_str().unwrap()).unwrap(); 215 | unsafe { floui_sys::CWebView_load_url(*self.inner, path.as_ptr()) } 216 | self 217 | } 218 | 219 | /// Load an html string 220 | pub fn load_html(self, html: &str) -> Self { 221 | let html = std::ffi::CString::new(html).unwrap(); 222 | unsafe { floui_sys::CWebView_load_html(*self.inner, html.as_ptr()) } 223 | self 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /src/widgets/mod.rs: -------------------------------------------------------------------------------- 1 | /// Button, toggle, check 2 | mod button; 3 | pub use button::*; 4 | /// Text and TextField 5 | mod text; 6 | pub use text::*; 7 | /// MainView, vertical and horizontal stack views 8 | mod stack; 9 | pub use stack::*; 10 | /// ScrollView, WebView, ImageView, Spacer, Slider 11 | mod misc; 12 | pub use misc::*; 13 | -------------------------------------------------------------------------------- /src/widgets/stack.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use floui_sys; 3 | use std::sync::Arc; 4 | 5 | /// Essentially a VStack, but takes the viewcontroller to initialize the view 6 | #[derive(Clone)] 7 | pub struct MainView { 8 | inner: Arc<*mut floui_sys::CMainView>, 9 | } 10 | 11 | unsafe impl Sync for MainView {} 12 | unsafe impl Send for MainView {} 13 | 14 | unsafe impl WidgetExt for MainView { 15 | fn inner(&self) -> *mut floui_sys::CWidget { 16 | *self.inner as _ 17 | } 18 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 19 | Self { 20 | inner: Arc::new(ptr as _), 21 | } 22 | } 23 | } 24 | 25 | impl MainView { 26 | /// Constructs a new widget 27 | pub fn new(vc: &ViewController, widgets: &[&dyn WidgetExt]) -> Self { 28 | let inner = unsafe { Arc::new(floui_sys::CMainView_new(*vc.inner)) }; 29 | for w in widgets { 30 | unsafe { 31 | floui_sys::CMainView_add(*inner, w.inner()); 32 | } 33 | } 34 | Self { inner } 35 | } 36 | 37 | /// Adds a widget 38 | pub fn add(&self, widget: &impl WidgetExt) { 39 | unsafe { 40 | floui_sys::CMainView_add(*self.inner, widget.inner()); 41 | } 42 | } 43 | 44 | /// Removes a widget 45 | pub fn remove(&self, widget: &impl WidgetExt) { 46 | unsafe { 47 | floui_sys::CMainView_remove(*self.inner, widget.inner()); 48 | } 49 | } 50 | 51 | /// Clears the widget 52 | pub fn clear(&self) { 53 | unsafe { 54 | floui_sys::CMainView_clear(*self.inner); 55 | } 56 | } 57 | } 58 | 59 | /// A vertical stack view 60 | #[derive(Clone)] 61 | pub struct VStack { 62 | inner: Arc<*mut floui_sys::CVStack>, 63 | } 64 | 65 | unsafe impl Sync for VStack {} 66 | unsafe impl Send for VStack {} 67 | 68 | unsafe impl WidgetExt for VStack { 69 | fn inner(&self) -> *mut floui_sys::CWidget { 70 | *self.inner as _ 71 | } 72 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 73 | Self { 74 | inner: Arc::new(ptr as _), 75 | } 76 | } 77 | } 78 | 79 | impl VStack { 80 | /// Constructs a new widget 81 | pub fn new(widgets: &[&dyn WidgetExt]) -> Self { 82 | let inner = unsafe { Arc::new(floui_sys::CVStack_new()) }; 83 | for w in widgets { 84 | unsafe { 85 | floui_sys::CVStack_add(*inner, w.inner()); 86 | } 87 | } 88 | Self { inner } 89 | } 90 | 91 | /// Adds a widget 92 | pub fn add(&self, widget: &impl WidgetExt) { 93 | unsafe { 94 | floui_sys::CVStack_add(*self.inner, widget.inner()); 95 | } 96 | } 97 | 98 | /// Removes a widget 99 | pub fn remove(&self, widget: &impl WidgetExt) { 100 | unsafe { 101 | floui_sys::CVStack_remove(*self.inner, widget.inner()); 102 | } 103 | } 104 | 105 | /// Clears the widget 106 | pub fn clear(&self) { 107 | unsafe { 108 | floui_sys::CVStack_clear(*self.inner); 109 | } 110 | } 111 | } 112 | 113 | /// A horizontal stack view 114 | #[derive(Clone)] 115 | pub struct HStack { 116 | inner: Arc<*mut floui_sys::CHStack>, 117 | } 118 | 119 | unsafe impl Sync for HStack {} 120 | unsafe impl Send for HStack {} 121 | 122 | unsafe impl WidgetExt for HStack { 123 | fn inner(&self) -> *mut floui_sys::CWidget { 124 | *self.inner as _ 125 | } 126 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 127 | Self { 128 | inner: Arc::new(ptr as _), 129 | } 130 | } 131 | } 132 | 133 | impl HStack { 134 | /// Constructs a new widget 135 | pub fn new(widgets: &[&dyn WidgetExt]) -> Self { 136 | let inner = unsafe { Arc::new(floui_sys::CHStack_new()) }; 137 | for w in widgets { 138 | unsafe { 139 | floui_sys::CHStack_add(*inner, w.inner()); 140 | } 141 | } 142 | Self { inner } 143 | } 144 | 145 | /// Adds a widget 146 | pub fn add(&self, widget: &impl WidgetExt) { 147 | unsafe { 148 | floui_sys::CHStack_add(*self.inner, widget.inner()); 149 | } 150 | } 151 | 152 | /// Removes a widget 153 | pub fn remove(&self, widget: &impl WidgetExt) { 154 | unsafe { 155 | floui_sys::CHStack_remove(*self.inner, widget.inner()); 156 | } 157 | } 158 | 159 | /// Clears the widget 160 | pub fn clear(&self) { 161 | unsafe { 162 | floui_sys::CHStack_clear(*self.inner); 163 | } 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /src/widgets/text.rs: -------------------------------------------------------------------------------- 1 | use crate::enums::Color; 2 | use crate::prelude::*; 3 | use floui_sys; 4 | use std::sync::Arc; 5 | 6 | /// A label 7 | #[derive(Clone)] 8 | pub struct Text { 9 | inner: Arc<*mut floui_sys::CText>, 10 | } 11 | 12 | unsafe impl Sync for Text {} 13 | unsafe impl Send for Text {} 14 | 15 | unsafe impl WidgetExt for Text { 16 | fn inner(&self) -> *mut floui_sys::CWidget { 17 | *self.inner as _ 18 | } 19 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 20 | Self { 21 | inner: Arc::new(ptr as _), 22 | } 23 | } 24 | } 25 | 26 | impl Text { 27 | /// Creates a new label 28 | pub fn new(label: &str) -> Self { 29 | let label = std::ffi::CString::new(label).unwrap(); 30 | let inner = unsafe { Arc::new(floui_sys::CText_new(label.as_ptr())) }; 31 | Self { inner } 32 | } 33 | 34 | /// Sets the text 35 | pub fn text(self, label: &str) -> Text { 36 | let label = std::ffi::CString::new(label).unwrap(); 37 | unsafe { floui_sys::CText_text(*self.inner, label.as_ptr()) }; 38 | self 39 | } 40 | 41 | /// Centers the text 42 | pub fn center(self) -> Text { 43 | unsafe { floui_sys::CText_center(*self.inner) }; 44 | self 45 | } 46 | 47 | /// Adjusts to the left 48 | pub fn left(self) -> Text { 49 | unsafe { floui_sys::CText_left(*self.inner) }; 50 | self 51 | } 52 | 53 | /// Adjusts to the right 54 | pub fn right(self) -> Text { 55 | unsafe { floui_sys::CText_right(*self.inner) }; 56 | self 57 | } 58 | 59 | /// Sets the text to be bold 60 | pub fn bold(self) -> Text { 61 | unsafe { floui_sys::CText_bold(*self.inner) }; 62 | self 63 | } 64 | 65 | /// Sets the text to be italic 66 | pub fn italic(self) -> Text { 67 | unsafe { floui_sys::CText_italic(*self.inner) }; 68 | self 69 | } 70 | 71 | /// Sets the text to be normal, the default 72 | pub fn normal(self) -> Text { 73 | unsafe { floui_sys::CText_normal(*self.inner) }; 74 | self 75 | } 76 | 77 | /// Sets the font size 78 | pub fn fontsize(self, size: i32) -> Text { 79 | unsafe { floui_sys::CText_fontsize(*self.inner, size) }; 80 | self 81 | } 82 | 83 | /// Sets the foreground color 84 | pub fn foreground(self, col: Color) -> Text { 85 | unsafe { floui_sys::CText_foreground(*self.inner, col.0) } 86 | self 87 | } 88 | } 89 | 90 | /// A text field 91 | #[derive(Clone)] 92 | pub struct TextField { 93 | inner: Arc<*mut floui_sys::CTextField>, 94 | } 95 | 96 | unsafe impl Sync for TextField {} 97 | unsafe impl Send for TextField {} 98 | 99 | unsafe impl WidgetExt for TextField { 100 | fn inner(&self) -> *mut floui_sys::CWidget { 101 | *self.inner as _ 102 | } 103 | fn from_widget_ptr(ptr: *mut floui_sys::CWidget) -> Self { 104 | Self { 105 | inner: Arc::new(ptr as _), 106 | } 107 | } 108 | } 109 | 110 | impl TextField { 111 | /// Creates a new TextField 112 | pub fn new() -> Self { 113 | let inner = unsafe { Arc::new(floui_sys::CTextField_new()) }; 114 | Self { inner } 115 | } 116 | 117 | /// Sets the text 118 | pub fn text(self, label: &str) -> TextField { 119 | let label = std::ffi::CString::new(label).unwrap(); 120 | unsafe { floui_sys::CTextField_text(*self.inner, label.as_ptr()) }; 121 | self 122 | } 123 | 124 | /// Centers the text 125 | pub fn center(self) -> TextField { 126 | unsafe { floui_sys::CTextField_center(*self.inner) }; 127 | self 128 | } 129 | 130 | /// Adjusts to the left 131 | pub fn left(self) -> TextField { 132 | unsafe { floui_sys::CTextField_left(*self.inner) }; 133 | self 134 | } 135 | 136 | /// Adjusts to the right 137 | pub fn right(self) -> TextField { 138 | unsafe { floui_sys::CTextField_right(*self.inner) }; 139 | self 140 | } 141 | 142 | /// Sets the font size 143 | pub fn fontsize(self, size: i32) -> TextField { 144 | unsafe { floui_sys::CTextField_fontsize(*self.inner, size) }; 145 | self 146 | } 147 | 148 | /// Sets the foreground color 149 | pub fn foreground(self, col: Color) -> TextField { 150 | unsafe { floui_sys::CTextField_foreground(*self.inner, col.0) } 151 | self 152 | } 153 | } 154 | --------------------------------------------------------------------------------