Adds a text_input example to act as a test.
- TextFieldDelegate methods needed to retain the string, otherwise it could crash under fast usage. - Work on improving the browser example; WIP.
This commit is contained in:
parent
420422187a
commit
80ec654d8d
|
@ -1,9 +1,12 @@
|
||||||
//! This example showcases setting up a basic application and window, setting up some views to
|
//! This example showcases setting up a basic application and window, setting up some views to
|
||||||
//! work with autolayout, and some basic ways to handle colors.
|
//! work with autolayout, and some basic ways to handle colors.
|
||||||
|
|
||||||
use cacao::webview::WebView;
|
use cacao::webview::{WebView, WebViewConfig, WebViewDelegate};
|
||||||
|
|
||||||
|
use cacao::input::{TextField, TextFieldDelegate};
|
||||||
|
|
||||||
use cacao::macos::{App, AppDelegate};
|
use cacao::macos::{App, AppDelegate};
|
||||||
|
use cacao::macos::toolbar::{Toolbar, ToolbarItem, ItemIdentifier, ToolbarDelegate};
|
||||||
use cacao::macos::menu::{Menu, MenuItem};
|
use cacao::macos::menu::{Menu, MenuItem};
|
||||||
use cacao::macos::window::{Window, WindowConfig, WindowDelegate};
|
use cacao::macos::window::{Window, WindowConfig, WindowDelegate};
|
||||||
|
|
||||||
|
@ -39,7 +42,6 @@ impl AppDelegate for BasicApp {
|
||||||
MenuItem::SelectAll
|
MenuItem::SelectAll
|
||||||
]),
|
]),
|
||||||
|
|
||||||
// Sidebar option is 11.0+ only.
|
|
||||||
Menu::new("View", vec![
|
Menu::new("View", vec![
|
||||||
MenuItem::EnterFullScreen
|
MenuItem::EnterFullScreen
|
||||||
]),
|
]),
|
||||||
|
@ -59,9 +61,50 @@ impl AppDelegate for BasicApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct URLBar;
|
||||||
|
|
||||||
|
impl TextFieldDelegate for URLBar {
|
||||||
|
const NAME: &'static str = "URLBar";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BrowserToolbar {
|
||||||
|
url_bar: TextField<URLBar>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BrowserToolbar {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
BrowserToolbar {
|
||||||
|
url_bar: TextField::with(URLBar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToolbarDelegate for BrowserToolbar {
|
||||||
|
const NAME: &'static str = "BrowserToolbar";
|
||||||
|
|
||||||
|
fn allowed_item_identifiers(&self) -> Vec<ItemIdentifier> { vec![] }
|
||||||
|
fn default_item_identifiers(&self) -> Vec<ItemIdentifier> { vec![] }
|
||||||
|
|
||||||
|
fn item_for(&self, _identifier: &str) -> &ToolbarItem { std::unreachable!(); }
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
pub struct WebViewInstance;
|
||||||
|
|
||||||
|
impl WebViewDelegate for WebViewInstance {}
|
||||||
|
|
||||||
struct AppWindow {
|
struct AppWindow {
|
||||||
content: WebView
|
toolbar: Toolbar<BrowserToolbar>,
|
||||||
|
content: WebView<WebViewInstance>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppWindow {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
AppWindow {
|
||||||
|
toolbar: Toolbar::new("com.example.BrowserToolbar", BrowserToolbar::new()),
|
||||||
|
content: WebView::with(WebViewConfig::default(), WebViewInstance::default())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowDelegate for AppWindow {
|
impl WindowDelegate for AppWindow {
|
||||||
|
@ -71,6 +114,7 @@ impl WindowDelegate for AppWindow {
|
||||||
window.set_title("Browser Example");
|
window.set_title("Browser Example");
|
||||||
window.set_minimum_content_size(400., 400.);
|
window.set_minimum_content_size(400., 400.);
|
||||||
|
|
||||||
|
window.set_toolbar(&self.toolbar);
|
||||||
window.set_content_view(&self.content);
|
window.set_content_view(&self.content);
|
||||||
|
|
||||||
self.content.load_url("https://www.duckduckgo.com/");
|
self.content.load_url("https://www.duckduckgo.com/");
|
||||||
|
@ -79,6 +123,6 @@ impl WindowDelegate for AppWindow {
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new("com.test.window", BasicApp {
|
App::new("com.test.window", BasicApp {
|
||||||
window: Window::with(WindowConfig::default(), AppWindow::default())
|
window: Window::with(WindowConfig::default(), AppWindow::new())
|
||||||
}).run();
|
}).run();
|
||||||
}
|
}
|
||||||
|
|
122
examples/text_input.rs
Normal file
122
examples/text_input.rs
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
//! This example showcases setting up a basic application and window, setting up some views to
|
||||||
|
//! work with autolayout, and some basic ways to handle colors.
|
||||||
|
|
||||||
|
use cacao::layout::{Layout, LayoutConstraint};
|
||||||
|
use cacao::input::{TextField, TextFieldDelegate};
|
||||||
|
use cacao::view::View;
|
||||||
|
|
||||||
|
use cacao::macos::{App, AppDelegate};
|
||||||
|
use cacao::macos::menu::{Menu, MenuItem};
|
||||||
|
use cacao::macos::window::{Window, WindowConfig, WindowDelegate};
|
||||||
|
|
||||||
|
struct BasicApp {
|
||||||
|
window: Window<AppWindow>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppDelegate for BasicApp {
|
||||||
|
fn did_finish_launching(&self) {
|
||||||
|
App::set_menu(vec![
|
||||||
|
Menu::new("", vec![
|
||||||
|
MenuItem::Services,
|
||||||
|
MenuItem::Separator,
|
||||||
|
MenuItem::Hide,
|
||||||
|
MenuItem::HideOthers,
|
||||||
|
MenuItem::ShowAll,
|
||||||
|
MenuItem::Separator,
|
||||||
|
MenuItem::Quit
|
||||||
|
]),
|
||||||
|
|
||||||
|
Menu::new("File", vec![
|
||||||
|
MenuItem::CloseWindow
|
||||||
|
]),
|
||||||
|
|
||||||
|
Menu::new("Edit", vec![
|
||||||
|
MenuItem::Undo,
|
||||||
|
MenuItem::Redo,
|
||||||
|
MenuItem::Separator,
|
||||||
|
MenuItem::Cut,
|
||||||
|
MenuItem::Copy,
|
||||||
|
MenuItem::Paste,
|
||||||
|
MenuItem::Separator,
|
||||||
|
MenuItem::SelectAll
|
||||||
|
]),
|
||||||
|
|
||||||
|
// Sidebar option is 11.0+ only.
|
||||||
|
Menu::new("View", vec![
|
||||||
|
MenuItem::EnterFullScreen
|
||||||
|
]),
|
||||||
|
|
||||||
|
Menu::new("Window", vec![
|
||||||
|
MenuItem::Minimize,
|
||||||
|
MenuItem::Zoom,
|
||||||
|
MenuItem::Separator,
|
||||||
|
MenuItem::new("Bring All to Front")
|
||||||
|
]),
|
||||||
|
|
||||||
|
Menu::new("Help", vec![])
|
||||||
|
]);
|
||||||
|
|
||||||
|
App::activate();
|
||||||
|
self.window.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct ConsoleLogger;
|
||||||
|
|
||||||
|
impl TextFieldDelegate for ConsoleLogger {
|
||||||
|
const NAME: &'static str = "ConsoleLogger";
|
||||||
|
|
||||||
|
fn text_should_begin_editing(&self, value: &str) -> bool {
|
||||||
|
println!("Should begin with value: {}", value);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn text_did_change(&self, value: &str) {
|
||||||
|
println!("Did change to: {}", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn text_did_end_editing(&self, value: &str) {
|
||||||
|
println!("Ended: {}", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct AppWindow {
|
||||||
|
input: TextField<ConsoleLogger>,
|
||||||
|
content: View
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppWindow {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
AppWindow {
|
||||||
|
input: TextField::with(ConsoleLogger),
|
||||||
|
content: View::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowDelegate for AppWindow {
|
||||||
|
const NAME: &'static str = "WindowDelegate";
|
||||||
|
|
||||||
|
fn did_load(&mut self, window: Window) {
|
||||||
|
window.set_title("Input Logger Example");
|
||||||
|
window.set_minimum_content_size(300., 300.);
|
||||||
|
|
||||||
|
self.content.add_subview(&self.input);
|
||||||
|
window.set_content_view(&self.content);
|
||||||
|
|
||||||
|
LayoutConstraint::activate(&[
|
||||||
|
self.input.center_x.constraint_equal_to(&self.content.center_x),
|
||||||
|
self.input.center_y.constraint_equal_to(&self.content.center_y),
|
||||||
|
self.input.width.constraint_equal_to_constant(280.)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
App::new("com.test.window", BasicApp {
|
||||||
|
window: Window::with(WindowConfig::default(), AppWindow::new())
|
||||||
|
}).run();
|
||||||
|
}
|
|
@ -13,19 +13,19 @@ use crate::utils::load;
|
||||||
/// Called when editing this text field has ended (e.g. user pressed enter).
|
/// Called when editing this text field has ended (e.g. user pressed enter).
|
||||||
extern "C" fn text_did_end_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
extern "C" fn text_did_end_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::from_retained(unsafe { msg_send![this, stringValue] });
|
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
||||||
view.text_did_end_editing(s.to_str());
|
view.text_did_end_editing(s.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn text_did_begin_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
extern "C" fn text_did_begin_editing<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::from_retained(unsafe { msg_send![this, stringValue] });
|
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
||||||
view.text_did_begin_editing(s.to_str());
|
view.text_did_begin_editing(s.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn text_did_change<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
extern "C" fn text_did_change<T: TextFieldDelegate>(this: &mut Object, _: Sel, _info: id) {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::from_retained(unsafe { msg_send![this, stringValue] });
|
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
||||||
view.text_did_change(s.to_str());
|
view.text_did_change(s.to_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ extern "C" fn text_should_begin_editing<T: TextFieldDelegate>(
|
||||||
_info: id,
|
_info: id,
|
||||||
) -> BOOL {
|
) -> BOOL {
|
||||||
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
let view = load::<T>(this, TEXTFIELD_DELEGATE_PTR);
|
||||||
let s = NSString::from_retained(unsafe { msg_send![this, stringValue] });
|
let s = NSString::retain(unsafe { msg_send![this, stringValue] });
|
||||||
|
|
||||||
match view.text_should_begin_editing(s.to_str()) {
|
match view.text_should_begin_editing(s.to_str()) {
|
||||||
true => YES,
|
true => YES,
|
||||||
|
|
Loading…
Reference in a new issue