choices options UI
BIN
nimanyatta_v001/.DS_Store
vendored
Normal file
1
nimanyatta_v001/.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
/dist/
|
/dist/
|
||||||
/target/
|
/target/
|
||||||
/Cargo.lock
|
/Cargo.lock
|
||||||
|
extra.txt
|
||||||
|
|
|
@ -3,5 +3,23 @@ name = "nimanyatta_v001"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "nimanyatta_v001"
|
||||||
|
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
makepad-widgets = { git = "https://github.com/makepad/makepad", branch = "rik" }
|
# makepad-widgets = { git = "https://github.com/makepad/makepad", branch = "rik", version = "0.6.0"}
|
||||||
|
makepad-widgets = { path = "../makepad/widgets", version = "0.6.0" }
|
||||||
|
makepad-draw = { path = "../makepad/draw", version = "0.6.0" }
|
||||||
|
# makepad-derive-widget = { path = "../makepad/widgets/derive_widget", version = "0.4.0" }
|
||||||
|
# makepad-derive-widget = { version = "0.4.0" }
|
||||||
|
makepad-derive-widget = { path = "../makepad/widgets/derive_widget", version = "0.4.0" }
|
||||||
|
makepad-wasm-bridge = { path = "../makepad/libs/wasm_bridge", version = "0.4.0" }
|
||||||
|
|
||||||
|
# makepad-widgets = { path = "../makepad/widgets" }
|
||||||
|
# makepad-widgets = { git = "https://github.com/makepad/makepad", branch = "rik" }
|
||||||
|
|
||||||
|
# [dependencies.nimanyatta_v001]
|
||||||
|
# version = "0.1.0"
|
||||||
|
# default-features = false
|
||||||
|
# features = ["wasm32"]
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Desktop in Debug Mode
|
||||||
|
|
||||||
|
cargo run
|
||||||
|
MAKEPAD=lines sudo cargo +nightly run nimanyatta_v001
|
||||||
|
|
||||||
|
# Desktop in Release Mode
|
||||||
|
|
||||||
|
cargo run --release
|
||||||
|
|
||||||
|
# Desktop in small size
|
||||||
|
|
||||||
|
cargo run --profile=small
|
||||||
|
|
||||||
|
# Android
|
||||||
|
|
||||||
|
cargo makepad android run --release
|
||||||
|
sudo cargo makepad android run -p nimanyatta_v001 --release
|
||||||
|
|
||||||
|
You can also customize the package name and application label
|
||||||
|
|
||||||
|
```
|
||||||
|
cargo run -p cargo-makepad --release -- android --package-name=com.yourcompany.myapp --app-label="My Example App" run -p makepad-example-ironfish
|
||||||
|
```
|
||||||
|
|
||||||
|
# wasm
|
||||||
|
|
||||||
|
sudo cargo makepad wasm run -p nimanyatta_v001 --release
|
||||||
|
|
||||||
|
RUSTFLAGS="-C linker-plugin-lto -C embed-bitcode=yes -C
|
||||||
|
codegen-units=1 -C opt-level=z" sudo cargo +nightly build -p nimanyatta_v001 --target=wasm32-unknown-unknown --release
|
||||||
|
cargo +stable run -p wasm_strip --release -- target/wasm32-unknown-unknown/release/nimanyatta_v001.wasm
|
BIN
nimanyatta_v001/resources/.DS_Store
vendored
Normal file
4
nimanyatta_v001/resources/back.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#000" d="M11.025 13.25a.748.748 0 0 1-1.281.53l-5.25-5.264a.75.75 0 0 1 0-1.06L9.717 2.22a.75.75 0 1 1 1.062 1.06L6.084 7.986l4.722 4.734a.748.748 0 0 1 .219.53z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 290 B |
4
nimanyatta_v001/resources/forward.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#000" d="M18.53 17.47a.75.75 0 1 1-1.06 1.06L12 13.06l-5.47 5.47a.748.748 0 0 1-1.06 0 .75.75 0 0 1 0-1.06L10.94 12 5.47 6.53a.75.75 0 1 1 1.06-1.06L12 10.94l5.47-5.47a.75.75 0 1 1 1.06 1.06L13.06 12l5.47 5.47z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 339 B |
BIN
nimanyatta_v001/resources/icons/drawable-mdpi/icon.png
Normal file
After Width: | Height: | Size: 11 KiB |
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path d="M 26.12 478.318 C 27.455 371.36 111.726 246.106 262.142 245.254 C 405.325 244.252 468.365 358.156 472.358 476.201 Z M 361.132 148.48 C 361.672 200.615 318.234 237.596 265.693 237.952 C 205.763 238.358 141.023 201.499 141.023 141.567 C 141.023 81.635 203.446 37.329 256.008 37.901 C 315.875 38.552 361.22 99.215 361.132 148.48 Z"/>
|
<path d="M 26.12 478.318 C 27.455 371.36 111.726 246.106 262.142 245.254 C 405.325 244.252 468.365 358.156 472.358 476.201 Z M 361.132 148.48 C 361.672 200.615 318.234 237.596 265.693 237.952 C 205.763 238.358 141.023 201.499 141.023 141.567 C 141.023 81.635 203.446 37.329 256.008 37.901 C 315.875 38.552 361.22 99.215 361.132 148.48 Z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 477 B After Width: | Height: | Size: 478 B |
4
nimanyatta_v001/resources/profile.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#000" d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zM6.858 18.752c.605-1.868 2.722-3.24 5.142-3.24 2.42 0 4.537 1.372 5.142 3.24C15.712 19.844 13.933 20.5 12 20.5s-3.712-.656-5.142-1.748zm11.469-1.095c-1.02-2.165-3.483-3.645-6.327-3.645s-5.307 1.48-6.327 3.645A8.456 8.456 0 0 1 3.5 12c0-4.687 3.813-8.5 8.5-8.5 4.687 0 8.5 3.813 8.5 8.5a8.456 8.456 0 0 1-2.173 5.657zM12 6a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7zm0 5.5c-1.103 0-2-.897-2-2s.897-2 2-2 2 .897 2 2-.897 2-2 2z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 627 B |
5
nimanyatta_v001/resources/status_info.svg
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="12" cy="12" r="6" fill="#fff"></circle>
|
||||||
|
<path fill="#3E6AE1" d="M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10 10-4.477 10-10S17.523 2 12 2zm.75 14.25a.75.75 0 0 1-1.5 0v-4.5a.75.75 0 0 1 1.5 0v4.5zM12 10a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 357 B |
4
nimanyatta_v001/resources/x.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill="#000" d="M18.53 17.47a.75.75 0 1 1-1.06 1.06L12 13.06l-5.47 5.47a.748.748 0 0 1-1.06 0 .75.75 0 0 1 0-1.06L10.94 12 5.47 6.53a.75.75 0 1 1 1.06-1.06L12 10.94l5.47-5.47a.75.75 0 1 1 1.06 1.06L13.06 12l5.47 5.47z"></path>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 339 B |
|
@ -1,4 +1,6 @@
|
||||||
|
// use crate::shared::stack_view_action::StackViewAction;
|
||||||
use makepad_widgets::*;
|
use makepad_widgets::*;
|
||||||
|
// use std::collections::HashMap;
|
||||||
|
|
||||||
live_design! {
|
live_design! {
|
||||||
|
|
||||||
|
@ -7,12 +9,20 @@ live_design! {
|
||||||
import makepad_widgets::theme_desktop_dark::*;
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
|
||||||
import crate::home::home_screen::HomeScreen;
|
import crate::home::home_screen::HomeScreen;
|
||||||
import crate::default_choice::default_choice_screen::DefaultChoiceScreen;
|
import crate::default_choice::default_choice_screen::DefaultChoice;
|
||||||
|
// import crate::default_choice::choose::Choose;
|
||||||
import crate::two::two_screen::TwoScreen;
|
import crate::two::two_screen::TwoScreen;
|
||||||
import crate::three::three_screen::ThreeScreen;
|
import crate::three::three_screen::ThreeScreen;
|
||||||
import crate::four::four_screen::FourScreen;
|
import crate::four::four_screen::FourScreen;
|
||||||
import crate::five::five_screen::FiveScreen;
|
import crate::five::five_screen::FiveScreen;
|
||||||
import crate::shared::styles::*;
|
import crate::shared::styles::*;
|
||||||
|
import crate::shared::steps::Choices;
|
||||||
|
import crate::shared::steps::ChoicesComponent;
|
||||||
|
import crate::shared::popup_menu::MenuItem;
|
||||||
|
// import crate::shared::header::DropDown;
|
||||||
|
|
||||||
|
// import crate::shared::stack_navigation::*;ChoicesComponent
|
||||||
|
|
||||||
|
|
||||||
REGULAR_TEXT = {
|
REGULAR_TEXT = {
|
||||||
font_size: (12),
|
font_size: (12),
|
||||||
|
@ -21,7 +31,7 @@ live_design! {
|
||||||
ICON_CHAT = dep("crate://self/resources/icons/chat.svg")
|
ICON_CHAT = dep("crate://self/resources/icons/chat.svg")
|
||||||
PHONE_CHAT = dep("crate://self/resources/icons/chat.svg")
|
PHONE_CHAT = dep("crate://self/resources/icons/chat.svg")
|
||||||
|
|
||||||
AppTab = <RadioButton> {
|
AppTab2 = <RadioButton> {
|
||||||
width: Fit,
|
width: Fit,
|
||||||
height: Fill,
|
height: Fill,
|
||||||
flow: Right,
|
flow: Right,
|
||||||
|
@ -31,8 +41,43 @@ live_design! {
|
||||||
// color: #000
|
// color: #000
|
||||||
draw_radio: {
|
draw_radio: {
|
||||||
radio_type: Tab,
|
radio_type: Tab,
|
||||||
color_active: #fff,
|
|
||||||
color_inactive: #fff,
|
instance border_width: 0.0
|
||||||
|
instance border_color: #0000
|
||||||
|
instance inset: vec4(0.0, 0.0, 0.0, 0.0)
|
||||||
|
instance radius: 2.5
|
||||||
|
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
(SIDEBAR_BG_COLOR),
|
||||||
|
(SIDEBAR_BG_COLOR_HOVER),
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
(SIDEBAR_BG_COLOR_SELECTED),
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_border_color(self) -> vec4 {
|
||||||
|
return self.border_color
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
sdf.box(
|
||||||
|
self.inset.x + self.border_width,
|
||||||
|
self.inset.y + self.border_width,
|
||||||
|
self.rect_size.x - (self.inset.x + self.inset.z + self.border_width * 2.0),
|
||||||
|
self.rect_size.y - (self.inset.y + self.inset.w + self.border_width * 2.0),
|
||||||
|
max(1.0, self.radius)
|
||||||
|
)
|
||||||
|
sdf.fill_keep(self.get_color())
|
||||||
|
if self.border_width > 0.0 {
|
||||||
|
sdf.stroke(self.get_border_color(), self.border_width)
|
||||||
|
}
|
||||||
|
return sdf.result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
draw_text: {
|
draw_text: {
|
||||||
color_selected: #000, //#0b0,
|
color_selected: #000, //#0b0,
|
||||||
|
@ -41,9 +86,114 @@ live_design! {
|
||||||
text_style: <H3_TEXT_REGULAR> {}
|
text_style: <H3_TEXT_REGULAR> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SIDEBAR_FONT_COLOR = #344054
|
||||||
|
SIDEBAR_FONT_COLOR_HOVER = #344054
|
||||||
|
SIDEBAR_FONT_COLOR_SELECTED = #127487
|
||||||
|
|
||||||
|
// SIDEBAR_BG_COLOR = #F8F8F8
|
||||||
|
SIDEBAR_BG_COLOR = #f
|
||||||
|
SIDEBAR_BG_COLOR_HOVER = #E2F1F199
|
||||||
|
SIDEBAR_BG_COLOR_SELECTED = #E2F1F199
|
||||||
|
|
||||||
|
AppTab = <RadioButton> {
|
||||||
|
width: 80,
|
||||||
|
height: 70,
|
||||||
|
padding: 0, margin: 0,
|
||||||
|
flow: Down, spacing: 8.0, align: {x: 0.5, y: 0.5}
|
||||||
|
|
||||||
|
icon_walk: {margin: 0, width: 30, height: 30}
|
||||||
|
label_walk: {margin: 0}
|
||||||
|
|
||||||
|
draw_radio: {
|
||||||
|
radio_type: Tab,
|
||||||
|
|
||||||
|
instance border_width: 0.0
|
||||||
|
instance border_color: #0000
|
||||||
|
instance inset: vec4(0.0, 0.0, 0.0, 0.0)
|
||||||
|
instance radius: 2.5
|
||||||
|
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
(SIDEBAR_BG_COLOR),
|
||||||
|
(SIDEBAR_BG_COLOR_HOVER),
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
(SIDEBAR_BG_COLOR_SELECTED),
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_border_color(self) -> vec4 {
|
||||||
|
return self.border_color
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
sdf.box(
|
||||||
|
self.inset.x + self.border_width,
|
||||||
|
self.inset.y + self.border_width,
|
||||||
|
self.rect_size.x - (self.inset.x + self.inset.z + self.border_width * 2.0),
|
||||||
|
self.rect_size.y - (self.inset.y + self.inset.w + self.border_width * 2.0),
|
||||||
|
max(1.0, self.radius)
|
||||||
|
)
|
||||||
|
sdf.fill_keep(self.get_color())
|
||||||
|
if self.border_width > 0.0 {
|
||||||
|
sdf.stroke(self.get_border_color(), self.border_width)
|
||||||
|
}
|
||||||
|
return sdf.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_text: {
|
||||||
|
color_unselected: (SIDEBAR_FONT_COLOR)
|
||||||
|
color_unselected_hover: (SIDEBAR_FONT_COLOR_HOVER)
|
||||||
|
color_selected: (SIDEBAR_FONT_COLOR_SELECTED)
|
||||||
|
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
self.color_unselected,
|
||||||
|
self.color_unselected_hover,
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
self.color_selected,
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_icon: {
|
||||||
|
instance color_unselected: (SIDEBAR_FONT_COLOR)
|
||||||
|
instance color_unselected_hover: (SIDEBAR_FONT_COLOR_HOVER)
|
||||||
|
instance color_selected: (SIDEBAR_FONT_COLOR_SELECTED)
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
self.color_unselected,
|
||||||
|
self.color_unselected_hover,
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
self.color_selected,
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
App = {{App}} {
|
App = {{App}} {
|
||||||
ui: <Window> {
|
ui: <Window> {
|
||||||
caption_bar = { margin: {left: -100}, visible: true, caption_label = {label = {text: "NiManyatta"}} },
|
caption_bar = {
|
||||||
|
margin: {
|
||||||
|
left: -100
|
||||||
|
},
|
||||||
|
visible: true,
|
||||||
|
caption_label = {
|
||||||
|
label = {
|
||||||
|
text: "NiManyatta"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
window: {inner_size: vec2(1280, 1000)},
|
||||||
|
|
||||||
body = {
|
body = {
|
||||||
show_bg: true
|
show_bg: true
|
||||||
|
@ -80,31 +230,36 @@ live_design! {
|
||||||
}
|
}
|
||||||
|
|
||||||
mobile_modes = <View> {
|
mobile_modes = <View> {
|
||||||
|
// spacing: 20
|
||||||
home_tab = <AppTab> {
|
<View> {
|
||||||
flow: Right,
|
// padding: { right: 60 }
|
||||||
align: {x: 0.0, y: 0.5}
|
home_tab = <AppTab> {
|
||||||
animator: {selected = {default: on}}
|
flow: Right,
|
||||||
label: ""
|
align: {x: 0.0, y: 0.5}
|
||||||
draw_icon: {
|
animator: {selected = {default: on}}
|
||||||
svg_file: (ICON_CHAT),
|
text: ""
|
||||||
fn get_color(self) -> vec4 {
|
draw_icon: {
|
||||||
return mix(
|
svg_file: (ICON_CHAT),
|
||||||
#000,
|
fn get_color(self) -> vec4 {
|
||||||
#016def,//#0b0,
|
return mix(
|
||||||
self.selected
|
#000,
|
||||||
)
|
#016def,//#0b0,
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
width: 80.0,
|
||||||
|
icon_walk: {width: 20, height: 20}
|
||||||
|
flow: Right, spacing: 5.0, align: {x: 0.5, y: 0.5}
|
||||||
}
|
}
|
||||||
width: Fill,
|
|
||||||
icon_walk: {width: 20, height: 20}
|
|
||||||
flow: Right, spacing: 5.0, align: {x: 0.2, y: 0.5}
|
|
||||||
}
|
}
|
||||||
|
<View> {
|
||||||
|
align: {x: 0.5}
|
||||||
two_tab = <AppTab> {
|
two_tab = <AppTab> {
|
||||||
flow: Right,
|
flow: Right,
|
||||||
align: {x: 0.0, y: 0.5}
|
align: {x: 0.0, y: 0.5}
|
||||||
animator: {selected = {default: on}}
|
// animator: {selected = {default: on}}
|
||||||
label: "2"
|
text: "2"
|
||||||
draw_icon: {
|
draw_icon: {
|
||||||
svg_file: (ICON_CHAT),
|
svg_file: (ICON_CHAT),
|
||||||
fn get_color(self) -> vec4 {
|
fn get_color(self) -> vec4 {
|
||||||
|
@ -115,15 +270,18 @@ live_design! {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
width: Fill,
|
width: 80.0,
|
||||||
icon_walk: {width: 20, height: 20}
|
icon_walk: {width: 20, height: 20}
|
||||||
flow: Down, spacing: 5.0, align: {x: 0.5, y: 0.5}
|
flow: Down, spacing: 5.0, align: {x: 0.5, y: 0.5}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
<View> {
|
||||||
|
align: {x: 0.5}
|
||||||
three_tab = <AppTab> {
|
three_tab = <AppTab> {
|
||||||
flow: Right,
|
flow: Right,
|
||||||
align: {x: 0.0, y: 0.5}
|
align: {x: 0.0, y: 0.5}
|
||||||
animator: {selected = {default: on}}
|
// animator: {selected = {default: on}}
|
||||||
label: "3"
|
text: "3"
|
||||||
draw_icon: {
|
draw_icon: {
|
||||||
svg_file: (ICON_CHAT),
|
svg_file: (ICON_CHAT),
|
||||||
fn get_color(self) -> vec4 {
|
fn get_color(self) -> vec4 {
|
||||||
|
@ -134,15 +292,18 @@ live_design! {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
width: Fill,
|
width: 80.0,
|
||||||
icon_walk: {width: 20, height: 20}
|
icon_walk: {width: 20, height: 20}
|
||||||
flow: Down, spacing: 5.0, align: {x: 0.5, y: 0.5}
|
flow: Down, spacing: 5.0, align: {x: 0.5, y: 0.5}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
<View> {
|
||||||
|
align: {x: 0.5}
|
||||||
four_tab = <AppTab> {
|
four_tab = <AppTab> {
|
||||||
flow: Right,
|
flow: Right,
|
||||||
align: {x: 0.0, y: 0.5}
|
align: {x: 0.0, y: 0.5}
|
||||||
animator: {selected = {default: on}}
|
// animator: {selected = {default: on}}
|
||||||
label: "4"
|
text: "4"
|
||||||
draw_icon: {
|
draw_icon: {
|
||||||
svg_file: (ICON_CHAT),
|
svg_file: (ICON_CHAT),
|
||||||
fn get_color(self) -> vec4 {
|
fn get_color(self) -> vec4 {
|
||||||
|
@ -153,28 +314,32 @@ live_design! {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
width: Fill,
|
width: 80.0,
|
||||||
icon_walk: {width: 20, height: 20}
|
icon_walk: {width: 20, height: 20}
|
||||||
flow: Down, spacing: 5.0, align: {x: 0.5, y: 0.5}
|
flow: Down, spacing: 5.0, align: {x: 0.5, y: 0.5}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
<View> {
|
||||||
|
align: {x: 1.0}
|
||||||
five_tab = <AppTab> {
|
five_tab = <AppTab> {
|
||||||
flow: Right,
|
flow: Right,
|
||||||
align: {x: 0.0, y: 0.5}
|
align: {x: 0.0, y: 0.5}
|
||||||
animator: {selected = {default: on}}
|
// animator: {selected = {default: on}}
|
||||||
label: ""
|
text: ""
|
||||||
draw_icon: {
|
draw_icon: {
|
||||||
svg_file: (PHONE_CHAT),
|
svg_file: (PHONE_CHAT),
|
||||||
fn get_color(self) -> vec4 {
|
fn get_color(self) -> vec4 {
|
||||||
return mix(
|
return mix(
|
||||||
#000,
|
#000,
|
||||||
#016def,//#0b0,
|
#016def,//#0b0,
|
||||||
self.selected
|
self.selected
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
width: 80.0,
|
||||||
|
icon_walk: {width: 20, height: 20}
|
||||||
|
flow: Right, spacing: 5.0, align: {x: 0.5, y: 0.5}
|
||||||
}
|
}
|
||||||
width: Fill,
|
|
||||||
icon_walk: {width: 20, height: 20}
|
|
||||||
flow: Right, spacing: 5.0, align: {x: 0.8, y: 0.5}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,10 +349,10 @@ live_design! {
|
||||||
padding: 0.0
|
padding: 0.0
|
||||||
|
|
||||||
home_frame = <HomeScreen> { visible: true }
|
home_frame = <HomeScreen> { visible: true }
|
||||||
kimanyatta_frame = <TwoScreen> {visible: false}
|
two_frame = <TwoScreen> {visible: false}
|
||||||
insurance_frame = <ThreeScreen> {visible: false}
|
three_frame = <ThreeScreen> {visible: false}
|
||||||
matatu_frame = <FourScreen> {visible: false}
|
four_frame = <FourScreen> {visible: false}
|
||||||
contactus_frame = <FiveScreen> {visible: false}
|
five_frame = <FiveScreen> {visible: false}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,12 +362,15 @@ live_design! {
|
||||||
title_container = {
|
title_container = {
|
||||||
title = {
|
title = {
|
||||||
text: "Help Me Choose"
|
text: "Help Me Choose"
|
||||||
|
draw_text: {
|
||||||
|
color: #000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
body = {
|
body = {
|
||||||
<DefaultChoiceScreen> {}
|
<DefaultChoice> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,6 +385,8 @@ app_main!(App);
|
||||||
pub struct App {
|
pub struct App {
|
||||||
#[live]
|
#[live]
|
||||||
ui: WidgetRef,
|
ui: WidgetRef,
|
||||||
|
// #[rust]
|
||||||
|
// navigation_destinations: HashMap<StackViewAction, LiveId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LiveRegister for App {
|
impl LiveRegister for App {
|
||||||
|
@ -224,6 +394,8 @@ impl LiveRegister for App {
|
||||||
crate::makepad_widgets::live_design(cx);
|
crate::makepad_widgets::live_design(cx);
|
||||||
crate::home::home_screen::live_design(cx);
|
crate::home::home_screen::live_design(cx);
|
||||||
crate::default_choice::default_choice_screen::live_design(cx);
|
crate::default_choice::default_choice_screen::live_design(cx);
|
||||||
|
crate::default_choice::choice::live_design(cx);
|
||||||
|
// crate::default_choice::choose::live_design(cx);
|
||||||
crate::two::two_screen::live_design(cx);
|
crate::two::two_screen::live_design(cx);
|
||||||
crate::three::three_screen::live_design(cx);
|
crate::three::three_screen::live_design(cx);
|
||||||
crate::four::four_screen::live_design(cx);
|
crate::four::four_screen::live_design(cx);
|
||||||
|
@ -231,12 +403,20 @@ impl LiveRegister for App {
|
||||||
|
|
||||||
crate::shared::styles::live_design(cx);
|
crate::shared::styles::live_design(cx);
|
||||||
crate::shared::custom_button::live_design(cx);
|
crate::shared::custom_button::live_design(cx);
|
||||||
|
crate::shared::round_slider::live_design(cx);
|
||||||
|
crate::shared::steps::live_design(cx);
|
||||||
|
crate::shared::cho::live_design(cx);
|
||||||
|
crate::shared::popup_menu::live_design(cx);
|
||||||
|
crate::shared::header::live_design(cx);
|
||||||
|
crate::shared::helpers::live_design(cx);
|
||||||
|
|
||||||
|
crate::shared::dropdown_menu::live_design(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LiveHook for App {
|
impl LiveHook for App {
|
||||||
// fn after_new_from_doc(&mut self, _cx: &mut Cx) {
|
// fn after_new_from_doc(&mut self, _cx: &mut Cx) {
|
||||||
// // self.init_navigation_destinations();
|
// self.init_navigation_destinations();
|
||||||
// }
|
// }
|
||||||
fn after_new_from_doc(&mut self, _cx: &mut Cx) {
|
fn after_new_from_doc(&mut self, _cx: &mut Cx) {
|
||||||
println!("after_new_from_doc(): starting some kind of a loop");
|
println!("after_new_from_doc(): starting some kind of a loop");
|
||||||
|
@ -287,6 +467,16 @@ impl MatchEvent for App {
|
||||||
|
|
||||||
let mut navigation = self.ui.stack_navigation(id!(navigation));
|
let mut navigation = self.ui.stack_navigation(id!(navigation));
|
||||||
navigation.handle_stack_view_actions(cx, &actions);
|
navigation.handle_stack_view_actions(cx, &actions);
|
||||||
|
|
||||||
|
for action in actions {
|
||||||
|
if let WindowAction::WindowGeomChange(ce) = action.as_widget_action().cast() {
|
||||||
|
let screen_width = ce.new_geom.inner_size.x * ce.new_geom.dpi_factor;
|
||||||
|
|
||||||
|
log!("x ===> {}", ce.new_geom.inner_size.x);
|
||||||
|
log!("dpi_factor ===> {}", ce.new_geom.dpi_factor);
|
||||||
|
log!("SCREEN_WIDTH ===> {}", screen_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,3 +486,26 @@ impl AppMain for App {
|
||||||
self.ui.handle_event(cx, event, &mut Scope::empty());
|
self.ui.handle_event(cx, event, &mut Scope::empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// impl Widget for App {
|
||||||
|
// fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
// // let label = self.view.label(id!(footer));
|
||||||
|
// // let cap = self.ui.widget(id!(caption_bar));
|
||||||
|
|
||||||
|
// // cap.apply_value_instance(cx, apply, index, nodes)
|
||||||
|
|
||||||
|
// DrawStep::done()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl App {
|
||||||
|
async fn _do_network_request(_cx: CxRef, _ui: WidgetRef, _url: &str) -> String {
|
||||||
|
"".to_string()
|
||||||
|
}
|
||||||
|
// fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
||||||
|
// if let Event::Draw(event) = event {
|
||||||
|
// return self.ui.draw_widget_all(&mut Cx2d::new(cx, event));
|
||||||
|
// }
|
||||||
|
// let actions = self.ui.handle_widget_event(cx, event);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
682
nimanyatta_v001/src/default_choice/cho.rs
Normal file
|
@ -0,0 +1,682 @@
|
||||||
|
// use makepad_widgets::*;
|
||||||
|
use crate::makepad_widgets::*;
|
||||||
|
const CHOICE_MAX_OFFSET: f64 = 700.0;
|
||||||
|
const SELECT_MAX_OFFSET: f64 = 500.0;
|
||||||
|
// use crate::shared::custom_button::CustomButton;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_draw::shader::std::*;
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
import crate::shared::styles::*;
|
||||||
|
import crate::shared::steps::StepNav;
|
||||||
|
import crate::shared::custom_button::CustomButton;
|
||||||
|
|
||||||
|
Indicator = <RoundedView> {
|
||||||
|
width: 100.0
|
||||||
|
height: 8.0
|
||||||
|
draw_bg: {
|
||||||
|
color: #f60,
|
||||||
|
radius: 2.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButChoices = <View>{
|
||||||
|
flow: Down,
|
||||||
|
show_bg: false
|
||||||
|
draw_bg: {
|
||||||
|
color: #000
|
||||||
|
}
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
but = <CustomButton> {
|
||||||
|
width: 300, height: 45,
|
||||||
|
text: "Option 1"
|
||||||
|
draw_bg: {
|
||||||
|
border_radius: 2.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SelectOptions = {{SelectOptions}} {
|
||||||
|
// page_titles: []
|
||||||
|
width: Fit, height: Fit,
|
||||||
|
// indicator_titles: []
|
||||||
|
flow: Down,
|
||||||
|
spacing: 10,
|
||||||
|
align: {x: 0.5, y: 0.5},
|
||||||
|
select_choices_values: []
|
||||||
|
selects_template: <ButChoices> {
|
||||||
|
flow: Down,
|
||||||
|
}
|
||||||
|
choice_page_offset: 0.0
|
||||||
|
animator: {
|
||||||
|
selectopt = {
|
||||||
|
default: restart,
|
||||||
|
restart = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {choice_page_offset: 500.0}
|
||||||
|
}
|
||||||
|
show = {
|
||||||
|
redraw: false,
|
||||||
|
from: {all: Forward {duration: 0}}
|
||||||
|
apply: {choice_page_offset: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
OptionC = {{Indicators}} {
|
||||||
|
width: Fit,
|
||||||
|
height: Fit,
|
||||||
|
flow: Down,
|
||||||
|
spacing: 5,
|
||||||
|
align: {x: 0.5, y: 0.5},
|
||||||
|
indicator_titles: []
|
||||||
|
template: <CustomButton> {
|
||||||
|
width: 100, height: Fit,
|
||||||
|
// margin: 0, padding: 0
|
||||||
|
text: "Option 1"
|
||||||
|
draw_bg: {
|
||||||
|
border_radius: 2.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StepsScreen = <View> {
|
||||||
|
// width: 300,
|
||||||
|
height: Fit,
|
||||||
|
flow: Down,
|
||||||
|
padding: 10.0
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
padding: 20,
|
||||||
|
spacing: 20,
|
||||||
|
step_title = <Label> {
|
||||||
|
// margin: {top: 1}
|
||||||
|
draw_text: {
|
||||||
|
text_style: <H2_TEXT_BOLD> {},
|
||||||
|
color: (COLOR_DOWN_6)
|
||||||
|
}
|
||||||
|
text: "Step One"
|
||||||
|
}
|
||||||
|
// <ButChoices> {}
|
||||||
|
<SelectOptions> {
|
||||||
|
// select_choices_values: [
|
||||||
|
// ["STP1-Option 1","STP1-Option 2","STP1-Option 3"],
|
||||||
|
// ["STP2-Option 1", "STP2-Option 2", "STP2-Option 3", "STP2-Option 4"],
|
||||||
|
// ["STP3-Option 1", "STP3-Option 2", "STP3-Option 3", "STP3-Option 4", "STP3-Option 5"]
|
||||||
|
// ]
|
||||||
|
select_choices_values: []
|
||||||
|
}
|
||||||
|
next = <CustomButton> {
|
||||||
|
width: 300, height: 50,
|
||||||
|
// margin: 0, padding: 0
|
||||||
|
text: "Next"
|
||||||
|
draw_bg: {
|
||||||
|
border_radius: 2.
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let border_color = #0157c0;
|
||||||
|
// let border_color = #016def; //#0157c0
|
||||||
|
let border_width = 0.5;
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
|
||||||
|
let body = mix(mix(#0157c0, #f, self.hover), #0157c0, self.pressed);
|
||||||
|
|
||||||
|
sdf.box(
|
||||||
|
1.,
|
||||||
|
1.,
|
||||||
|
self.rect_size.x - 2.0,
|
||||||
|
self.rect_size.y - 2.0,
|
||||||
|
self.border_radius
|
||||||
|
)
|
||||||
|
sdf.fill_keep(body)
|
||||||
|
|
||||||
|
sdf.stroke(
|
||||||
|
border_color,
|
||||||
|
border_width
|
||||||
|
)
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
IndicatorCheckBox = <CheckBox> {
|
||||||
|
width: Fill,
|
||||||
|
height: 35,
|
||||||
|
margin: {left: 1},
|
||||||
|
label_walk: {margin: {top: 15}}
|
||||||
|
draw_check: {
|
||||||
|
uniform size: 3.5;
|
||||||
|
instance open: 0.0
|
||||||
|
uniform length: 3.0
|
||||||
|
uniform width: 1.0
|
||||||
|
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
match self.check_type {
|
||||||
|
CheckType::Check => {
|
||||||
|
let sz = self.size;
|
||||||
|
let left = sz + 1.;
|
||||||
|
let up = sz + 7;
|
||||||
|
let c = self.rect_size * vec2(0.5, 0.5);
|
||||||
|
sdf.box(
|
||||||
|
left,
|
||||||
|
c.y - up,
|
||||||
|
25. * sz + 5,
|
||||||
|
1.8 * sz,
|
||||||
|
1.8
|
||||||
|
);
|
||||||
|
|
||||||
|
sdf.fill(#232323);
|
||||||
|
sdf.stroke(#000, 0.5 + 0.5 * self.dpi_dilate);
|
||||||
|
|
||||||
|
let isz = sz * 0.5;
|
||||||
|
let ileft = isz + 3;
|
||||||
|
let iup = sz + 7;
|
||||||
|
sdf.box(
|
||||||
|
ileft,
|
||||||
|
c.y - iup,
|
||||||
|
25. * sz + 5,
|
||||||
|
1.8 * sz,
|
||||||
|
1.8
|
||||||
|
);
|
||||||
|
sdf.fill(mix(#fff0, #016def, self.selected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_text: {text_style: <THEME_FONT_LABEL> {}}
|
||||||
|
}
|
||||||
|
Indicators = {{Indicators}} {
|
||||||
|
width: Fit,
|
||||||
|
height: Fit,
|
||||||
|
flow: Right,
|
||||||
|
// flow: Down,
|
||||||
|
spacing: 5,
|
||||||
|
// align: {x: 0.5, y: 0.5},
|
||||||
|
indicator_titles: []
|
||||||
|
template: <IndicatorCheckBox> {
|
||||||
|
width: 100, height: 20,
|
||||||
|
margin: 0, padding: 0
|
||||||
|
// flow: Right,
|
||||||
|
// flow: Down,
|
||||||
|
align: {x: 0.5, y: 0.5},
|
||||||
|
text: "Here",
|
||||||
|
draw_text: {
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return #f60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_check: {
|
||||||
|
check_type: Check,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Steps = {{Steps}} {
|
||||||
|
page_titles: []
|
||||||
|
choices_values: []
|
||||||
|
page_template: <StepsScreen> { }
|
||||||
|
// custom_button: <CustomButton>{
|
||||||
|
// width: Fill, height: Fit,
|
||||||
|
// text: "Next"
|
||||||
|
// draw_bg: {
|
||||||
|
// border_radius: 2.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
choice_page_offset: 0.0
|
||||||
|
animator: {
|
||||||
|
choice = {
|
||||||
|
default: restart,
|
||||||
|
restart = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {choice_page_offset: 400.0}
|
||||||
|
}
|
||||||
|
show = {
|
||||||
|
redraw: true,
|
||||||
|
from: {all: Forward {duration: 0.5}}
|
||||||
|
apply: {choice_page_offset: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Choose = {{Choose}}{
|
||||||
|
// debug: A
|
||||||
|
width: 400,
|
||||||
|
height: 480,
|
||||||
|
flow: Down,
|
||||||
|
padding: 20, spacing: 10
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
<Indicators>{
|
||||||
|
indicator_titles: [
|
||||||
|
"Step One",
|
||||||
|
"Step Two",
|
||||||
|
"Step Three"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
<Steps>{
|
||||||
|
page_template: <StepsScreen> {}
|
||||||
|
page_titles: ["Step One", "Step Two", "Step Three" ]
|
||||||
|
choices_values: [
|
||||||
|
["STP1-Option 1"],
|
||||||
|
["STP2-Option 1", "STP2-Option 2", "STP2-Option 3"],
|
||||||
|
["STP3-Option 1", "STP3-Option 2"]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#[derive(Live, LiveHook, Widget)]
|
||||||
|
pub struct Choose {
|
||||||
|
#[deref]
|
||||||
|
view: View,
|
||||||
|
}
|
||||||
|
impl Widget for Choose {
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
self.view.draw_walk_all(cx, scope, walk);
|
||||||
|
// log!("Choose: draw_walk");
|
||||||
|
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
self.view.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct Indicators {
|
||||||
|
#[redraw]
|
||||||
|
#[rust]
|
||||||
|
area: Area,
|
||||||
|
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
indicator_titles: Vec<String>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
items: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for Indicators {
|
||||||
|
fn after_apply(&mut self, cx: &mut Cx, _apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
|
||||||
|
// let tags = ["test1", "test2", "test3"];
|
||||||
|
// log!("Indicators: after_apply");
|
||||||
|
|
||||||
|
self.items.clear();
|
||||||
|
for (i, title_text) in self.indicator_titles.iter().enumerate() {
|
||||||
|
// for (i, title_text) in tags.iter().enumerate() {
|
||||||
|
let item_id = LiveId::from_str(&format!("items{}", i));
|
||||||
|
let item_widget = WidgetRef::new_from_ptr(cx, self.template);
|
||||||
|
// item_widget.apply_over(cx, live! {label = { text: (title_text) }});
|
||||||
|
item_widget.apply_over(cx, live! {text: (title_text) });
|
||||||
|
self.items.insert(item_id, item_widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Indicators {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
for (_id, item) in self.items.iter_mut() {
|
||||||
|
item.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
cx.begin_turtle(walk, self.layout);
|
||||||
|
//Indicators
|
||||||
|
// log!("Indicators: draw_walk");
|
||||||
|
for (_id, item) in self.items.iter_mut() {
|
||||||
|
// let _ = item.draw(cx, scope);
|
||||||
|
let _ = item.draw_all(cx, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
cx.end_turtle_with_area(&mut self.area);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct Steps {
|
||||||
|
#[redraw]
|
||||||
|
#[rust]
|
||||||
|
area: Area,
|
||||||
|
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
// #[live]
|
||||||
|
// draw_bg: DrawQuad,
|
||||||
|
// #[live]
|
||||||
|
// custom_button: CustomButton,
|
||||||
|
#[live]
|
||||||
|
page_titles: Vec<String>,
|
||||||
|
#[live]
|
||||||
|
choices_values: Vec<Vec<String>>,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
items: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
// #[live]
|
||||||
|
// choices_values: Vec<LiveValue>,
|
||||||
|
#[live]
|
||||||
|
page_template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
options_template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[rust(0)]
|
||||||
|
current_page: u8,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
pages: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
choice_page_offset: f64,
|
||||||
|
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for Steps {
|
||||||
|
fn after_new_from_doc(&mut self, cx: &mut Cx) {
|
||||||
|
log!("Steps::after_new_from_doc");
|
||||||
|
// fn after_apply(&mut self, cx: &mut Cx, _apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
|
||||||
|
// log!("Steps: after_apply");
|
||||||
|
for (idx, title_text) in self.page_titles.iter().enumerate() {
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", idx));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.page_template)
|
||||||
|
});
|
||||||
|
|
||||||
|
page.label(id!(step_title))
|
||||||
|
.set_text_and_redraw(cx, &format!("{}", &title_text.as_str()))
|
||||||
|
}
|
||||||
|
// for (idx, title_text_vec) in self.choices_values.iter().enumerate() {
|
||||||
|
// log!("Options: {:?}", &title_text_vec);
|
||||||
|
// // for (_idx, title_text) in title_text_vec.iter().enumerate() {
|
||||||
|
// // log!("Options: {:?}", &title_text);
|
||||||
|
// let widget_id = LiveId::from_str(&format!("page{}", idx));
|
||||||
|
// let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
// WidgetRef::new_from_ptr(cx, self.page_template)
|
||||||
|
// });
|
||||||
|
// for (_idx, title_text) in title_text_vec.iter().enumerate() {
|
||||||
|
// log!("Options: {:?}", &title_text);
|
||||||
|
// page.button(id!(but))
|
||||||
|
// .set_text_and_redraw(cx, &format!("{}", &title_text.as_str()))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Steps {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, _scope: &mut Scope) {
|
||||||
|
// //Options
|
||||||
|
// for (_id, item) in self.items.iter_mut() {
|
||||||
|
// item.handle_event(cx, event, scope);
|
||||||
|
// }
|
||||||
|
// log!("Steps: handle_event");
|
||||||
|
if self.animator_handle_event(cx, event).must_redraw() {
|
||||||
|
self.redraw(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire the "show" animation when the "restart" animation is done
|
||||||
|
if self.animator.animator_in_state(cx, id!(choice.restart)) {
|
||||||
|
self.animator_play(cx, id!(choice.show));
|
||||||
|
}
|
||||||
|
|
||||||
|
// match event.hits(cx, self.custom_button.area()) {
|
||||||
|
match event.hits(cx, self.area) {
|
||||||
|
Hit::FingerUp(fe) => {
|
||||||
|
if fe.is_over {
|
||||||
|
// Do not fire a new animation if the choice is already animating
|
||||||
|
if !self.animator.is_track_animating(cx, id!(choice)) {
|
||||||
|
self.update_current_page();
|
||||||
|
self.animator_play(cx, id!(choice.restart));
|
||||||
|
//self.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// fn redraw(&mut self, cx: &mut Cx) {
|
||||||
|
// self.area.redraw(cx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
// let walk = self.walk(cx);
|
||||||
|
self.draw_walkd(cx, scope, walk);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Steps {
|
||||||
|
fn draw_walkd(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) {
|
||||||
|
cx.begin_turtle(walk, Layout::default());
|
||||||
|
|
||||||
|
self.draw_page_with_offset(cx, scope, self.current_page, self.choice_page_offset, walk);
|
||||||
|
|
||||||
|
let prev_page_idx =
|
||||||
|
(self.current_page + self.page_titles.len() as u8 - 1) % self.page_titles.len() as u8;
|
||||||
|
self.draw_page_with_offset(
|
||||||
|
cx,
|
||||||
|
scope,
|
||||||
|
prev_page_idx,
|
||||||
|
self.choice_page_offset - CHOICE_MAX_OFFSET,
|
||||||
|
walk,
|
||||||
|
);
|
||||||
|
|
||||||
|
cx.end_turtle_with_area(&mut self.area);
|
||||||
|
// cx.end_turtle_with_area(&mut self.custom_button.area());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_page_with_offset(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx2d,
|
||||||
|
scope: &mut Scope,
|
||||||
|
index: u8,
|
||||||
|
offset: f64,
|
||||||
|
walk: Walk,
|
||||||
|
) {
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", index));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.page_template)
|
||||||
|
});
|
||||||
|
|
||||||
|
let _ = page.draw_walk(cx, scope, walk.with_margin_left(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_current_page(&mut self) {
|
||||||
|
self.current_page = (self.current_page + 1) % self.page_titles.len() as u8;
|
||||||
|
log!("Steps::update_current_page: {:?}", &self.current_page);
|
||||||
|
// self.current_page = (self.current_page + 1) % self.choices_values.len() as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct SelectOptions {
|
||||||
|
#[redraw]
|
||||||
|
#[rust]
|
||||||
|
area: Area,
|
||||||
|
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
page_titles: Vec<String>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
select_choices_values: Vec<Vec<String>>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
selects_template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
options_template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[rust(0)]
|
||||||
|
current_page: u8,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
pages: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
choice_page_offset: f64,
|
||||||
|
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
}
|
||||||
|
impl LiveHook for SelectOptions {
|
||||||
|
fn after_new_from_doc(&mut self, cx: &mut Cx) {
|
||||||
|
log!("SelectOptions::after_new_from_doc");
|
||||||
|
// fn after_apply(&mut self, cx: &mut Cx, _apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
|
||||||
|
// log!("SelectOptions: after_apply");
|
||||||
|
self.select_choices_values = vec![
|
||||||
|
vec![
|
||||||
|
"STP1-Option 1".to_string(),
|
||||||
|
"STP1-Option 2".to_string(),
|
||||||
|
"STP1-Option 3".to_string(),
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
"STP2-Option 1".to_string(),
|
||||||
|
"STP2-Option 2".to_string(),
|
||||||
|
"STP2-Option 3".to_string(),
|
||||||
|
"STP2-Option 4".to_string(),
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
"STP3-Option 1".to_string(),
|
||||||
|
"STP3-Option 2".to_string(),
|
||||||
|
"STP3-Option 3".to_string(),
|
||||||
|
"STP3-Option 4".to_string(),
|
||||||
|
"STP3-Option 5".to_string(),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
for (idx, title_text_vec) in self.select_choices_values.iter().enumerate() {
|
||||||
|
// log!("Options: {:?}", &title_text_vec);
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", idx));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.selects_template)
|
||||||
|
});
|
||||||
|
for (_idx, title_text) in title_text_vec.iter().enumerate() {
|
||||||
|
// log!("Options: {:?}", &title_text);
|
||||||
|
page.button(id!(but))
|
||||||
|
.set_text_and_redraw(cx, &format!("{}", &title_text.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for SelectOptions {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, _scope: &mut Scope) {
|
||||||
|
if self.animator_handle_event(cx, event).must_redraw() {
|
||||||
|
self.redraw(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire the "show" animation when the "restart" animation is done
|
||||||
|
if self.animator.animator_in_state(cx, id!(selectopt.restart)) {
|
||||||
|
self.animator_play(cx, id!(selectopt.show));
|
||||||
|
}
|
||||||
|
|
||||||
|
// match event.hits(cx, self.custom_button.area()) {
|
||||||
|
match event.hits(cx, self.area) {
|
||||||
|
Hit::FingerUp(fe) => {
|
||||||
|
if fe.is_over {
|
||||||
|
// Do not fire a new animation if the selectopt is already animating
|
||||||
|
if !self.animator.is_track_animating(cx, id!(selectopt)) {
|
||||||
|
self.update_current_page();
|
||||||
|
self.animator_play(cx, id!(selectopt.restart));
|
||||||
|
// self.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// fn redraw(&mut self, cx: &mut Cx) {
|
||||||
|
// self.area.redraw(cx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
// let walk = self.walk(cx);
|
||||||
|
self.draw_walkd(cx, scope, walk);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SelectOptions {
|
||||||
|
fn draw_walkd(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) {
|
||||||
|
// cx.begin_turtle(walk, Layout::default());
|
||||||
|
cx.begin_turtle(walk, self.layout);
|
||||||
|
|
||||||
|
let mut arr: Vec<Vec<String>> = Vec::new();
|
||||||
|
for inner_vec in &self.select_choices_values {
|
||||||
|
// Append the inner vector to the new variable
|
||||||
|
arr.push(inner_vec.clone());
|
||||||
|
}
|
||||||
|
// let arr = self.add_to();
|
||||||
|
|
||||||
|
for (_idx, choices_arr) in arr.iter().enumerate() {
|
||||||
|
for (inneridx, _innerj) in choices_arr.iter().enumerate() {
|
||||||
|
// let prev_page_idx = (idx as u8 + choices_arr.len() as u8 - inneridx as u8)
|
||||||
|
// % choices_arr.len() as u8;
|
||||||
|
// log!(
|
||||||
|
// "prev_page_idx/index: {:?}===offset: {:?}",
|
||||||
|
// inneridx,
|
||||||
|
// self.choice_page_offset - SELECT_MAX_OFFSET
|
||||||
|
// );
|
||||||
|
// if prev_page_idx == 1 {
|
||||||
|
self.draw_page_with_offset(
|
||||||
|
cx,
|
||||||
|
scope,
|
||||||
|
inneridx as u8,
|
||||||
|
self.choice_page_offset - SELECT_MAX_OFFSET,
|
||||||
|
walk,
|
||||||
|
);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// self.draw_page_with_offset(cx, scope, self.current_page, self.choice_page_offset, walk);
|
||||||
|
|
||||||
|
// let prev_page_idx = (self.current_page + self.select_choices_values.len() as u8 - 0)
|
||||||
|
// % self.select_choices_values.len() as u8;
|
||||||
|
// self.draw_page_with_offset(
|
||||||
|
// cx,
|
||||||
|
// scope,
|
||||||
|
// prev_page_idx,
|
||||||
|
// self.choice_page_offset - SELECT_MAX_OFFSET,
|
||||||
|
// walk,
|
||||||
|
// );
|
||||||
|
|
||||||
|
cx.end_turtle_with_area(&mut self.area);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_page_with_offset(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx2d,
|
||||||
|
scope: &mut Scope,
|
||||||
|
index: u8,
|
||||||
|
offset: f64,
|
||||||
|
walk: Walk,
|
||||||
|
) {
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", index));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.selects_template)
|
||||||
|
});
|
||||||
|
|
||||||
|
// let _ = page.draw_all(cx, scope);
|
||||||
|
let _ = page.draw_walk(cx, scope, walk.with_margin_left(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_current_page(&mut self) {
|
||||||
|
self.current_page = (self.current_page + 1) % self.select_choices_values.len() as u8;
|
||||||
|
log!(
|
||||||
|
"SelectOptions::update_current_page: {:?}",
|
||||||
|
&self.current_page
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
938
nimanyatta_v001/src/default_choice/choice.rs
Normal file
|
@ -0,0 +1,938 @@
|
||||||
|
// use makepad_widgets::*;
|
||||||
|
use crate::makepad_widgets::*;
|
||||||
|
const CHOICE_MAX_OFFSET: f64 = 700.0;
|
||||||
|
const SELECT_MAX_OFFSET: f64 = 500.0;
|
||||||
|
// use crate::shared::custom_button::CustomButton;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_draw::shader::std::*;
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
import crate::shared::styles::*;
|
||||||
|
import crate::shared::steps::StepNav;
|
||||||
|
import crate::shared::custom_button::CustomButton;
|
||||||
|
|
||||||
|
Indicator = <RoundedView> {
|
||||||
|
width: 100.0
|
||||||
|
height: 8.0
|
||||||
|
draw_bg: {
|
||||||
|
color: #f60,
|
||||||
|
radius: 2.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButChoices1 = <View>{
|
||||||
|
flow: Down,
|
||||||
|
show_bg: false
|
||||||
|
draw_bg: {
|
||||||
|
color: #000
|
||||||
|
}
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
but = <CustomButton> {
|
||||||
|
width: 300, height: 45,
|
||||||
|
text: "Option 1"
|
||||||
|
draw_bg: {
|
||||||
|
border_radius: 2.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ButChoices2 = <View>{
|
||||||
|
flow: Down,
|
||||||
|
show_bg: false
|
||||||
|
draw_bg: {
|
||||||
|
color: #000
|
||||||
|
}
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
but = <RadioButton> {
|
||||||
|
width: 300, height: 45,
|
||||||
|
text: "Option 1"
|
||||||
|
// draw_bg: {
|
||||||
|
// border_radius: 2.
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SIDEBAR_FONT_COLOR = #344054
|
||||||
|
SIDEBAR_FONT_COLOR_HOVER = #344054
|
||||||
|
SIDEBAR_FONT_COLOR_SELECTED = #127487
|
||||||
|
|
||||||
|
SIDEBAR_BG_COLOR = #f
|
||||||
|
SIDEBAR_BG_COLOR_HOVER = #E2F1F199
|
||||||
|
SIDEBAR_BG_COLOR_SELECTED = #E2F1F199
|
||||||
|
|
||||||
|
ButChoices = <ButtonGroup>{
|
||||||
|
// debug: A
|
||||||
|
flow: Down,
|
||||||
|
show_bg: false
|
||||||
|
draw_bg: {
|
||||||
|
color: #000
|
||||||
|
}
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
but = <View> {
|
||||||
|
// debug: A
|
||||||
|
width: 300, height: 45,
|
||||||
|
butchoice = <RadioButtonTextual> {
|
||||||
|
width: Fill,
|
||||||
|
height: 70,
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
|
||||||
|
text: "Option 1"
|
||||||
|
label_walk: { width: Fit, height: 34.0 }
|
||||||
|
icon_walk: {width: 80, height: 80}
|
||||||
|
|
||||||
|
draw_radio: {
|
||||||
|
radio_type: Tab,
|
||||||
|
|
||||||
|
instance border_width: 0.0
|
||||||
|
instance border_color: #344054
|
||||||
|
instance inset: vec4(0.0, 0.0, 0.0, 0.0)
|
||||||
|
instance radius: 2.5
|
||||||
|
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
(SIDEBAR_BG_COLOR),
|
||||||
|
(SIDEBAR_BG_COLOR_HOVER),
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
(SIDEBAR_BG_COLOR_SELECTED),
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_border_color(self) -> vec4 {
|
||||||
|
return self.border_color
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let border_color = #0157c0;
|
||||||
|
let border_width = 0.5;
|
||||||
|
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
sdf.box(
|
||||||
|
self.inset.x + self.border_width,
|
||||||
|
self.inset.y + self.border_width,
|
||||||
|
self.rect_size.x - (self.inset.x + self.inset.z + self.border_width * 2.0),
|
||||||
|
self.rect_size.y - (self.inset.y + self.inset.w + self.border_width * 2.0),
|
||||||
|
max(1.0, self.radius)
|
||||||
|
)
|
||||||
|
sdf.fill_keep(self.get_color())
|
||||||
|
if self.border_width > 0.0 {
|
||||||
|
sdf.stroke(self.get_border_color(), self.border_width)
|
||||||
|
}
|
||||||
|
sdf.stroke(
|
||||||
|
border_color,
|
||||||
|
border_width
|
||||||
|
)
|
||||||
|
return sdf.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_text: {
|
||||||
|
color_unselected: (SIDEBAR_FONT_COLOR)
|
||||||
|
color_unselected_hover: (SIDEBAR_FONT_COLOR_HOVER)
|
||||||
|
color_selected: (SIDEBAR_FONT_COLOR_SELECTED)
|
||||||
|
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
self.color_unselected,
|
||||||
|
self.color_unselected_hover,
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
self.color_selected,
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// <ButtonGroup> {
|
||||||
|
// height: Fit
|
||||||
|
// flow: Right
|
||||||
|
// align: { x: 0.0, y: 0.5 }
|
||||||
|
// radiotabs_demo = <View> {
|
||||||
|
// width: Fit, height: Fit,
|
||||||
|
// radio1 = <RadioButtonTab> { label: "Option 1" }
|
||||||
|
// radio2 = <RadioButtonTab> { label: "Option 2" }
|
||||||
|
// radio3 = <RadioButtonTab> { label: "Option 3" }
|
||||||
|
// radio4 = <RadioButtonTab> { label: "Option 4" }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
SelectOptions = {{SelectOptions}} {
|
||||||
|
// page_titles: []
|
||||||
|
width: Fit, height: Fit,
|
||||||
|
// indicator_titles: []
|
||||||
|
flow: Down,
|
||||||
|
spacing: 10,
|
||||||
|
align: {x: 0.5, y: 0.5},
|
||||||
|
select_choices_values: []
|
||||||
|
selects_template: <ButChoices> {
|
||||||
|
flow: Down,
|
||||||
|
}
|
||||||
|
choice_page_offset: 0.0
|
||||||
|
animator: {
|
||||||
|
selectopt = {
|
||||||
|
default: restart,
|
||||||
|
restart = {
|
||||||
|
ease: ExpDecay {d1: 0.80, d2: 0.97}
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {choice_page_offset: 500.0}
|
||||||
|
}
|
||||||
|
show = {
|
||||||
|
redraw: true,
|
||||||
|
ease: ExpDecay {d1: 0.80, d2: 0.97}
|
||||||
|
// from: {all: Forward {duration: 0}}
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {choice_page_offset: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
OptionC = {{Indicators}} {
|
||||||
|
width: Fit,
|
||||||
|
height: Fit,
|
||||||
|
flow: Down,
|
||||||
|
spacing: 5,
|
||||||
|
align: {x: 0.5, y: 0.5},
|
||||||
|
indicator_titles: []
|
||||||
|
template: <CustomButton> {
|
||||||
|
width: 100, height: Fit,
|
||||||
|
// margin: 0, padding: 0
|
||||||
|
text: "Option 1"
|
||||||
|
draw_bg: {
|
||||||
|
border_radius: 2.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StepsScreen = <View> {
|
||||||
|
// debug: A
|
||||||
|
// width: 300,
|
||||||
|
height: Fit,
|
||||||
|
flow: Down,
|
||||||
|
// padding: 10.0
|
||||||
|
// align: {y: 0.5}
|
||||||
|
align: {y: 0.5}
|
||||||
|
// padding: 20,
|
||||||
|
spacing: (THEME_SPACE_2),
|
||||||
|
|
||||||
|
|
||||||
|
title = <View> {
|
||||||
|
// debug: A
|
||||||
|
// align: {x: 0.1}
|
||||||
|
// padding: {left: 10.0},
|
||||||
|
height: Fit
|
||||||
|
spacing: 0,
|
||||||
|
step_title = <Label> {
|
||||||
|
// margin: {top: 10.0, left: 10.0}
|
||||||
|
draw_text: {
|
||||||
|
// text_style: <H2_TEXT_BOLD> {},
|
||||||
|
text_style: <REGULAR_TEXT>{font_size: 12.},
|
||||||
|
color: (COLOR_DOWN_6)
|
||||||
|
}
|
||||||
|
text: "Step One"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// <ButChoices> {}
|
||||||
|
avail_options = <View> {
|
||||||
|
// debug: A
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
height: Fit
|
||||||
|
<SelectOptions> {
|
||||||
|
// select_choices_values: [
|
||||||
|
// ["STP1-Option 1","STP1-Option 2","STP1-Option 3"],
|
||||||
|
// ["STP2-Option 1", "STP2-Option 2", "STP2-Option 3", "STP2-Option 4"],
|
||||||
|
// ["STP3-Option 1", "STP3-Option 2", "STP3-Option 3", "STP3-Option 4", "STP3-Option 5"]
|
||||||
|
// ]
|
||||||
|
select_choices_values: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
IndicatorCheckBox = <CheckBox> {
|
||||||
|
width: Fill,
|
||||||
|
height: 35,
|
||||||
|
margin: {left: 1},
|
||||||
|
label_walk: {margin: {top: 15, bottom: 10}}
|
||||||
|
draw_check: {
|
||||||
|
uniform size: 3.5;
|
||||||
|
instance open: 0.0
|
||||||
|
uniform length: 3.0
|
||||||
|
uniform width: 1.0
|
||||||
|
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
match self.check_type {
|
||||||
|
CheckType::Check => {
|
||||||
|
let sz = self.size;
|
||||||
|
let left = sz + 1.;
|
||||||
|
let up = sz + 7;
|
||||||
|
let c = self.rect_size * vec2(0.5, 0.5);
|
||||||
|
sdf.box(
|
||||||
|
left,
|
||||||
|
c.y - up,
|
||||||
|
25. * sz + 5,
|
||||||
|
1.8 * sz,
|
||||||
|
1.8
|
||||||
|
);
|
||||||
|
|
||||||
|
sdf.fill(#232323);
|
||||||
|
sdf.stroke(#000, 0.5 + 0.5 * self.dpi_dilate);
|
||||||
|
|
||||||
|
let isz = sz * 0.5;
|
||||||
|
let ileft = isz + 3;
|
||||||
|
let iup = sz + 7;
|
||||||
|
sdf.box(
|
||||||
|
ileft,
|
||||||
|
c.y - iup,
|
||||||
|
25. * sz + 5,
|
||||||
|
1.8 * sz,
|
||||||
|
1.8
|
||||||
|
);
|
||||||
|
sdf.fill(mix(#fff0, #016def, self.selected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_text: {text_style: <THEME_FONT_LABEL> {}}
|
||||||
|
}
|
||||||
|
Indicators = {{Indicators}} {
|
||||||
|
width: Fit,
|
||||||
|
height: Fit,
|
||||||
|
flow: Right,
|
||||||
|
// flow: Down,
|
||||||
|
spacing: 5,
|
||||||
|
// align: {x: 0.5, y: 0.5},
|
||||||
|
indicator_titles: []
|
||||||
|
template: <IndicatorCheckBox> {
|
||||||
|
width: 100, height: 20,
|
||||||
|
margin: 0, padding: 0
|
||||||
|
// flow: Right,
|
||||||
|
// flow: Down,
|
||||||
|
align: {x: 0.5, y: 0.5},
|
||||||
|
text: "Here",
|
||||||
|
draw_text: {
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return #f60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_check: {
|
||||||
|
check_type: Check,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Steps = {{Steps}} {
|
||||||
|
// debug: A
|
||||||
|
page_titles: []
|
||||||
|
choices_values: []
|
||||||
|
|
||||||
|
page_template: <StepsScreen> { }
|
||||||
|
// custom_button: <CustomButton>{
|
||||||
|
// width: Fill, height: Fit,
|
||||||
|
// text: "Next"
|
||||||
|
// draw_bg: {
|
||||||
|
// border_radius: 2.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
choice_page_offset: 0.0
|
||||||
|
animator: {
|
||||||
|
choice = {
|
||||||
|
default: restart,
|
||||||
|
restart = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {choice_page_offset: 400.0}
|
||||||
|
}
|
||||||
|
show = {
|
||||||
|
redraw: true,
|
||||||
|
from: {all: Forward {duration: 0.5}}
|
||||||
|
apply: {choice_page_offset: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Choose = {{Choose}}{
|
||||||
|
// debug: A
|
||||||
|
width: 400,
|
||||||
|
// height: 500,
|
||||||
|
height: 488,
|
||||||
|
// height: Fit,
|
||||||
|
padding: 20, spacing: 20
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
<View>{
|
||||||
|
// debug: A
|
||||||
|
flow: Down,
|
||||||
|
width: Fit,
|
||||||
|
// height: Fill,
|
||||||
|
// spacing: 20
|
||||||
|
align: {y: 0.5}
|
||||||
|
<View>{
|
||||||
|
// debug: A
|
||||||
|
height: Fit,
|
||||||
|
width: Fit,
|
||||||
|
margin: {bottom: 20.0}
|
||||||
|
<Indicators>{
|
||||||
|
indicator_titles: [
|
||||||
|
"Step One",
|
||||||
|
"Step Two",
|
||||||
|
"Step Three"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
back = <View> {
|
||||||
|
// debug: A
|
||||||
|
width: Fit, height: Fit,
|
||||||
|
back_left_button = <Button> {
|
||||||
|
width: Fit, height: Fit,
|
||||||
|
icon_walk: {width: 10, height: Fit}
|
||||||
|
text: "Back"
|
||||||
|
draw_text: {
|
||||||
|
text_style: <REGULAR_TEXT>{font_size: 12.},
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
// return #016def
|
||||||
|
return mix(mix(#000, #000, self.hover), #000, self.pressed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_bg: {
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_icon: {
|
||||||
|
svg_file: dep("crate://self/resources/back.svg"),
|
||||||
|
// color: (THEME_COLOR_TEXT_DEFAULT);
|
||||||
|
color: #000;
|
||||||
|
brightness: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
<Steps>{
|
||||||
|
page_template: <StepsScreen> {}
|
||||||
|
page_titles: ["Step One", "Step Two", "Step Three" ]
|
||||||
|
choices_values: [
|
||||||
|
["STP1-Option 1"],
|
||||||
|
["STP2-Option 1", "STP2-Option 2", "STP2-Option 3"],
|
||||||
|
["STP3-Option 1", "STP3-Option 2"]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
next_button = <View> {
|
||||||
|
// debug: A
|
||||||
|
height: Fit
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
next = <CustomButton> {
|
||||||
|
// debug: A
|
||||||
|
width: 300, height: 50,
|
||||||
|
// margin: 0, padding: 0
|
||||||
|
text: "Next"
|
||||||
|
draw_text: {
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
// return #016def // 0160C0
|
||||||
|
return mix(mix(#f0, #016def, self.hover), #f0, self.pressed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_bg: {
|
||||||
|
border_radius: 2.
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let border_color = #0157c0;
|
||||||
|
// let border_color = #016def; //#0157c0
|
||||||
|
let border_width = 0.5;
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
|
||||||
|
let body = mix(mix(#0157c0, #f, self.hover), #0157c0, self.pressed);
|
||||||
|
|
||||||
|
sdf.box(
|
||||||
|
1.,
|
||||||
|
1.,
|
||||||
|
self.rect_size.x - 2.0,
|
||||||
|
self.rect_size.y - 2.0,
|
||||||
|
self.border_radius
|
||||||
|
)
|
||||||
|
sdf.fill_keep(body)
|
||||||
|
|
||||||
|
sdf.stroke(
|
||||||
|
border_color,
|
||||||
|
border_width
|
||||||
|
)
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
#[derive(Live, LiveHook, Widget)]
|
||||||
|
pub struct Choose {
|
||||||
|
#[deref]
|
||||||
|
view: View,
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
#[rust]
|
||||||
|
screen_width: f64,
|
||||||
|
}
|
||||||
|
impl Widget for Choose {
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
self.view.draw_walk_all(cx, scope, walk);
|
||||||
|
// log!("Choose: draw_walk");
|
||||||
|
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
self.view.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl WidgetMatchEvent for Choose {
|
||||||
|
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, _scope: &mut Scope) {
|
||||||
|
let back_left_button_clicked = self.button(id!(back_left_button)).clicked(&actions);
|
||||||
|
if back_left_button_clicked {
|
||||||
|
self.next_page_view(cx);
|
||||||
|
}
|
||||||
|
let next_button_clicked = self.button(id!(next)).clicked(&actions);
|
||||||
|
if next_button_clicked {
|
||||||
|
self.next_page_view(cx);
|
||||||
|
}
|
||||||
|
for action in actions {
|
||||||
|
if let WindowAction::WindowGeomChange(ce) = action.as_widget_action().cast() {
|
||||||
|
self.screen_width = ce.new_geom.inner_size.x * ce.new_geom.dpi_factor;
|
||||||
|
|
||||||
|
log!("SCREEN_WIDTH ===> {}", self.screen_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Choose {
|
||||||
|
fn back_left_view(&mut self, cx: &mut Cx) {
|
||||||
|
// // Fire the "show" animation when the "restart" animation is done
|
||||||
|
// if self.animator.animator_in_state(cx, id!(choice.restart)) {
|
||||||
|
// self.animator_play(cx, id!(choice.show));
|
||||||
|
// }
|
||||||
|
self.animator_play(cx, id!(choice.show));
|
||||||
|
// cx.widget_action(
|
||||||
|
// self.widget_uid(),
|
||||||
|
// &HeapLiveIdPath::default(),
|
||||||
|
// StackNavigationTransitionAction::HideBegin,
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
fn next_page_view(&mut self, cx: &mut Cx) {
|
||||||
|
// // Fire the "show" animation when the "restart" animation is done
|
||||||
|
// if self.animator.animator_in_state(cx, id!(choice.restart)) {
|
||||||
|
// self.animator_play(cx, id!(choice.show));
|
||||||
|
// }
|
||||||
|
self.animator_play(cx, id!(choice.show));
|
||||||
|
// cx.widget_action(
|
||||||
|
// self.widget_uid(),
|
||||||
|
// &HeapLiveIdPath::default(),
|
||||||
|
// StackNavigationTransitionAction::HideBegin,
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct Indicators {
|
||||||
|
#[redraw]
|
||||||
|
#[rust]
|
||||||
|
area: Area,
|
||||||
|
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
indicator_titles: Vec<String>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
items: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for Indicators {
|
||||||
|
fn after_apply(&mut self, cx: &mut Cx, _apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
|
||||||
|
// let tags = ["test1", "test2", "test3"];
|
||||||
|
// log!("Indicators: after_apply");
|
||||||
|
|
||||||
|
self.items.clear();
|
||||||
|
for (i, title_text) in self.indicator_titles.iter().enumerate() {
|
||||||
|
// for (i, title_text) in tags.iter().enumerate() {
|
||||||
|
let item_id = LiveId::from_str(&format!("items{}", i));
|
||||||
|
let item_widget = WidgetRef::new_from_ptr(cx, self.template);
|
||||||
|
// item_widget.apply_over(cx, live! {label = { text: (title_text) }});
|
||||||
|
item_widget.apply_over(cx, live! {text: (title_text) });
|
||||||
|
self.items.insert(item_id, item_widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Indicators {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
for (_id, item) in self.items.iter_mut() {
|
||||||
|
item.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
cx.begin_turtle(walk, self.layout);
|
||||||
|
//Indicators
|
||||||
|
let mut arr: Vec<WidgetRef> = Vec::new();
|
||||||
|
for (_idx, inner_vec) in self.items.iter_mut() {
|
||||||
|
// Append the inner vector to the new variable
|
||||||
|
arr.push(inner_vec.clone());
|
||||||
|
}
|
||||||
|
for (inneridx, indicator_arr) in arr.iter().enumerate() {
|
||||||
|
let index: u8 = inneridx as u8;
|
||||||
|
let widget_id = LiveId::from_str(&format!("items{}", index));
|
||||||
|
let item = self.items.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.template)
|
||||||
|
});
|
||||||
|
let _ = item.draw_all(cx, scope);
|
||||||
|
}
|
||||||
|
// for (_id, item) in self.items.iter_mut() {
|
||||||
|
// // let _ = item.draw(cx, scope);
|
||||||
|
// let _ = item.draw_all(cx, scope);
|
||||||
|
// }
|
||||||
|
|
||||||
|
cx.end_turtle_with_area(&mut self.area);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct Steps {
|
||||||
|
#[redraw]
|
||||||
|
#[rust]
|
||||||
|
area: Area,
|
||||||
|
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
page_titles: Vec<String>,
|
||||||
|
#[live]
|
||||||
|
choices_values: Vec<Vec<String>>,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
items: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
page_template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
options_template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[rust(0)]
|
||||||
|
current_page: u8,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
pages: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
choice_page_offset: f64,
|
||||||
|
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for Steps {
|
||||||
|
fn after_new_from_doc(&mut self, cx: &mut Cx) {
|
||||||
|
log!("Steps::after_new_from_doc");
|
||||||
|
for (idx, title_text) in self.page_titles.iter().enumerate() {
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", idx));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.page_template)
|
||||||
|
});
|
||||||
|
|
||||||
|
page.label(id!(step_title))
|
||||||
|
.set_text_and_redraw(cx, &format!("{}", &title_text.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Steps {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
for (_id, page) in self.pages.iter_mut() {
|
||||||
|
page.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
if self.animator_handle_event(cx, event).must_redraw() {
|
||||||
|
self.redraw(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire the "show" animation when the "restart" animation is done
|
||||||
|
if self.animator.animator_in_state(cx, id!(choice.restart)) {
|
||||||
|
self.animator_play(cx, id!(choice.show));
|
||||||
|
}
|
||||||
|
|
||||||
|
// // match event.hits(cx, self.custom_button.area()) {
|
||||||
|
// match event.hits(cx, self.area) {
|
||||||
|
// Hit::FingerUp(fe) => {
|
||||||
|
// if fe.is_over {
|
||||||
|
// // Do not fire a new animation if the choice is already animating
|
||||||
|
// if !self.animator.is_track_animating(cx, id!(choice)) {
|
||||||
|
// self.update_current_page();
|
||||||
|
// self.animator_play(cx, id!(choice.restart));
|
||||||
|
// //self.redraw(cx);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// _ => (),
|
||||||
|
// };
|
||||||
|
}
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
self.draw_walkd(cx, scope, walk);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl WidgetMatchEvent for Steps {
|
||||||
|
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, _scope: &mut Scope) {
|
||||||
|
for action in actions {
|
||||||
|
if let WindowAction::WindowGeomChange(ce) = action.as_widget_action().cast() {
|
||||||
|
let screen_width = ce.new_geom.inner_size.x * ce.new_geom.dpi_factor;
|
||||||
|
|
||||||
|
log!("SCREEN_WIDTH ===> {}", screen_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Steps {
|
||||||
|
fn draw_walkd(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) {
|
||||||
|
cx.begin_turtle(walk, Layout::default());
|
||||||
|
|
||||||
|
self.draw_page_with_offset(cx, scope, self.current_page, self.choice_page_offset, walk);
|
||||||
|
|
||||||
|
let prev_page_idx =
|
||||||
|
(self.current_page + self.page_titles.len() as u8 - 1) % self.page_titles.len() as u8;
|
||||||
|
self.draw_page_with_offset(
|
||||||
|
cx,
|
||||||
|
scope,
|
||||||
|
prev_page_idx,
|
||||||
|
self.choice_page_offset - CHOICE_MAX_OFFSET,
|
||||||
|
walk,
|
||||||
|
);
|
||||||
|
|
||||||
|
cx.end_turtle_with_area(&mut self.area);
|
||||||
|
// cx.end_turtle_with_area(&mut self.custom_button.area());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_page_with_offset(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx2d,
|
||||||
|
scope: &mut Scope,
|
||||||
|
index: u8,
|
||||||
|
offset: f64,
|
||||||
|
walk: Walk,
|
||||||
|
) {
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", index));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.page_template)
|
||||||
|
});
|
||||||
|
|
||||||
|
let _ = page.draw_walk(cx, scope, walk.with_margin_left(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_current_page(&mut self) {
|
||||||
|
self.current_page = (self.current_page + 1) % self.page_titles.len() as u8;
|
||||||
|
log!("Steps::update_current_page: {:?}", &self.current_page);
|
||||||
|
// self.current_page = (self.current_page + 1) % self.choices_values.len() as u8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct SelectOptions {
|
||||||
|
#[redraw]
|
||||||
|
#[rust]
|
||||||
|
area: Area,
|
||||||
|
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
page_titles: Vec<String>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
select_choices_values: Vec<Vec<String>>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
selects_template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
options_template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[rust(0)]
|
||||||
|
current_page: u8,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
pages: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
choice_page_offset: f64,
|
||||||
|
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
}
|
||||||
|
impl LiveHook for SelectOptions {
|
||||||
|
fn after_new_from_doc(&mut self, cx: &mut Cx) {
|
||||||
|
log!("SelectOptions::after_new_from_doc");
|
||||||
|
// fn after_apply(&mut self, cx: &mut Cx, _apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
|
||||||
|
// log!("SelectOptions: after_apply");
|
||||||
|
self.select_choices_values = vec![
|
||||||
|
vec![
|
||||||
|
"STP1-Option 1".to_string(),
|
||||||
|
"STP1-Option 2".to_string(),
|
||||||
|
"STP1-Option 3".to_string(),
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
"STP2-Option 1".to_string(),
|
||||||
|
"STP2-Option 2".to_string(),
|
||||||
|
"STP2-Option 3".to_string(),
|
||||||
|
"STP2-Option 4".to_string(),
|
||||||
|
],
|
||||||
|
vec![
|
||||||
|
"STP3-Option 1".to_string(),
|
||||||
|
"STP3-Option 2".to_string(),
|
||||||
|
"STP3-Option 3".to_string(),
|
||||||
|
"STP3-Option 4".to_string(),
|
||||||
|
"STP3-Option 5".to_string(),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
// for (idx, title_text_vec) in self.select_choices_values[2].iter().enumerate() {
|
||||||
|
// let widget_id = LiveId::from_str(&format!("page{}", idx));
|
||||||
|
// let page = WidgetRef::new_from_ptr(cx, self.selects_template);
|
||||||
|
// // page.apply_over(cx, live! { label = {text:(title_text_vec)}});
|
||||||
|
// page.apply_over(cx, live! {label: (title_text_vec) });
|
||||||
|
// self.pages.insert(widget_id, page);
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (idx, title_text_vec) in self.select_choices_values[0].iter().enumerate() {
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", idx));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.selects_template)
|
||||||
|
});
|
||||||
|
// page.button(id!(but))
|
||||||
|
page.radio_button(id!(butchoice))
|
||||||
|
// page.label(id!(but))
|
||||||
|
.set_text_and_redraw(cx, &format!("{}", &title_text_vec.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for SelectOptions {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
for (_id, page) in self.pages.iter_mut() {
|
||||||
|
page.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
// if self.animator_handle_event(cx, event).must_redraw() {
|
||||||
|
// self.redraw(cx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // Fire the "show" animation when the "restart" animation is done
|
||||||
|
// if self.animator.animator_in_state(cx, id!(selectopt.restart)) {
|
||||||
|
// self.animator_play(cx, id!(selectopt.show));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // match event.hits(cx, self.custom_button.area()) {
|
||||||
|
// match event.hits(cx, self.area) {
|
||||||
|
// Hit::FingerUp(fe) => {
|
||||||
|
// if fe.is_over {
|
||||||
|
// // Do not fire a new animation if the selectopt is already animating
|
||||||
|
// if !self.animator.is_track_animating(cx, id!(selectopt)) {
|
||||||
|
// self.update_current_page();
|
||||||
|
// self.animator_play(cx, id!(selectopt.restart));
|
||||||
|
// // self.redraw(cx);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// _ => (),
|
||||||
|
// };
|
||||||
|
}
|
||||||
|
// fn redraw(&mut self, cx: &mut Cx) {
|
||||||
|
// self.area.redraw(cx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
// let walk = self.walk(cx);
|
||||||
|
self.draw_walkd(cx, scope, walk);
|
||||||
|
// println!("=>{:?}", self.select_choices_values[0].clone());
|
||||||
|
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl WidgetMatchEvent for SelectOptions {
|
||||||
|
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, _scope: &mut Scope) {
|
||||||
|
for action in actions {
|
||||||
|
if let WindowAction::WindowGeomChange(ce) = action.as_widget_action().cast() {
|
||||||
|
let screen_width = ce.new_geom.inner_size.x * ce.new_geom.dpi_factor;
|
||||||
|
|
||||||
|
log!("SCREEN_WIDTH ===> {}", screen_width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl SelectOptions {
|
||||||
|
fn draw_walkd(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) {
|
||||||
|
// cx.begin_turtle(walk, Layout::default());
|
||||||
|
cx.begin_turtle(walk, self.layout);
|
||||||
|
let mut arr: Vec<Vec<String>> = Vec::new();
|
||||||
|
for inner_vec in &self.select_choices_values {
|
||||||
|
// Append the inner vector to the new variable
|
||||||
|
arr.push(inner_vec.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (inneridx, choices_arr) in arr[0].iter().enumerate() {
|
||||||
|
// println!("=>{:?}", choices_arr);
|
||||||
|
// for (inneridx, _innerj) in choices_arr.iter().enumerate() {
|
||||||
|
// self.draw_page_with_offset(
|
||||||
|
// cx,
|
||||||
|
// scope,
|
||||||
|
// inneridx as u8,
|
||||||
|
// self.choice_page_offset - SELECT_MAX_OFFSET,
|
||||||
|
// walk,
|
||||||
|
// );
|
||||||
|
let offset: f64 = self.choice_page_offset - SELECT_MAX_OFFSET;
|
||||||
|
let index: u8 = inneridx as u8;
|
||||||
|
// println!("=>{:?}", index);
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", index));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.selects_template)
|
||||||
|
});
|
||||||
|
// let _ = page.draw_walk_all(cx, scope, walk.with_margin_left(offset));
|
||||||
|
//.draw_all(cx, scope);
|
||||||
|
|
||||||
|
let _ = page.draw_walk(cx, scope, walk.with_margin_left(offset));
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
cx.end_turtle_with_area(&mut self.area);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_page_with_offset(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx2d,
|
||||||
|
scope: &mut Scope,
|
||||||
|
index: u8,
|
||||||
|
offset: f64,
|
||||||
|
walk: Walk,
|
||||||
|
) {
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", index));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.selects_template)
|
||||||
|
});
|
||||||
|
|
||||||
|
// let _ = page.draw_all(cx, scope);
|
||||||
|
let _ = page.draw_walk(cx, scope, walk.with_margin_left(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_current_page(&mut self) {
|
||||||
|
self.current_page = (self.current_page + 1) % self.select_choices_values[0].len() as u8;
|
||||||
|
log!(
|
||||||
|
"SelectOptions::update_current_page: {:?}",
|
||||||
|
&self.current_page
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
297
nimanyatta_v001/src/default_choice/choose.rs
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
use makepad_widgets::*;
|
||||||
|
const CHOICE_MAX_OFFSET: f64 = 400.0;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_draw::shader::std::*;
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
import crate::shared::styles::*;
|
||||||
|
import crate::shared::custom_button::CustomButton;
|
||||||
|
|
||||||
|
IndicatorCheckBox = <CheckBox> {
|
||||||
|
width: Fill,
|
||||||
|
height: 35,
|
||||||
|
margin: {left: 1},
|
||||||
|
label_walk: {margin: {top: 15}}
|
||||||
|
draw_check: {
|
||||||
|
uniform size: 3.5;
|
||||||
|
instance open: 0.0
|
||||||
|
uniform length: 3.0
|
||||||
|
uniform width: 1.0
|
||||||
|
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
match self.check_type {
|
||||||
|
CheckType::Check => {
|
||||||
|
let sz = self.size;
|
||||||
|
let left = sz + 1.;
|
||||||
|
let up = sz + 7;
|
||||||
|
let c = self.rect_size * vec2(0.5, 0.5);
|
||||||
|
sdf.box(
|
||||||
|
left,
|
||||||
|
c.y - up,
|
||||||
|
25. * sz + 5,
|
||||||
|
1.8 * sz,
|
||||||
|
1.8
|
||||||
|
);
|
||||||
|
|
||||||
|
sdf.fill(#232323);
|
||||||
|
sdf.stroke(#000, 0.5 + 0.5 * self.dpi_dilate);
|
||||||
|
|
||||||
|
let isz = sz * 0.5;
|
||||||
|
let ileft = isz + 3;
|
||||||
|
let iup = sz + 7;
|
||||||
|
sdf.box(
|
||||||
|
ileft,
|
||||||
|
c.y - iup,
|
||||||
|
25. * sz + 5,
|
||||||
|
1.8 * sz,
|
||||||
|
1.8
|
||||||
|
);
|
||||||
|
sdf.fill(mix(#fff0, #016def, self.selected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_text: {text_style: <THEME_FONT_LABEL> {}}
|
||||||
|
}
|
||||||
|
// Indicators = {{Indicators}}{
|
||||||
|
// Fit,
|
||||||
|
// flow: Right,
|
||||||
|
// spacing: 5,
|
||||||
|
// align: {x: 0.5, y: 0.5},
|
||||||
|
// indicator_titles: []
|
||||||
|
// template: <IndicatorCheckBox> {
|
||||||
|
// width: 100, height: 20,
|
||||||
|
// margin: 0, padding: 0
|
||||||
|
// flow: Right,
|
||||||
|
// align: {x: 0.5, y: 0.5},
|
||||||
|
// text: "Here",
|
||||||
|
// draw_text: {
|
||||||
|
// fn get_color(self) -> vec4 {
|
||||||
|
// return #f60;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// draw_check: {
|
||||||
|
// check_type: Check,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
Choose = {{Choose}}{
|
||||||
|
height: Fill, width: Fill
|
||||||
|
// flow: Down
|
||||||
|
<Indicators>{
|
||||||
|
// indicator_titles: [
|
||||||
|
// "Step One",
|
||||||
|
// "Step Two",
|
||||||
|
// "Step Three"
|
||||||
|
// ]
|
||||||
|
}
|
||||||
|
<Steps>{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, LiveHook, Widget)]
|
||||||
|
pub struct Choose {
|
||||||
|
#[deref]
|
||||||
|
view: View,
|
||||||
|
}
|
||||||
|
impl Widget for Choose {
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
self.view.draw_walk_all(cx, scope, walk);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
self.view.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct Indicators {
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
#[redraw]
|
||||||
|
#[live]
|
||||||
|
draw_bg: DrawQuad,
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
#[live]
|
||||||
|
indicator_titles: Vec<String>,
|
||||||
|
#[live]
|
||||||
|
template: Option<LivePtr>,
|
||||||
|
#[rust]
|
||||||
|
items: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
}
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct Steps {
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
#[redraw]
|
||||||
|
#[live]
|
||||||
|
draw_bg: DrawQuad,
|
||||||
|
// #[redraw] #[rust] area:Area,
|
||||||
|
// #[walk] walk:Walk,
|
||||||
|
#[live]
|
||||||
|
page_titles: Vec<String>,
|
||||||
|
#[live]
|
||||||
|
choices_values: Vec<Vec<String>>,
|
||||||
|
#[rust]
|
||||||
|
items: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
#[live]
|
||||||
|
page_template: Option<LivePtr>,
|
||||||
|
#[live]
|
||||||
|
options_template: Option<LivePtr>,
|
||||||
|
#[rust(0)]
|
||||||
|
current_page: u8,
|
||||||
|
#[rust]
|
||||||
|
pages: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
#[live]
|
||||||
|
choice_page_offset: f64,
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for Indicators {
|
||||||
|
fn after_apply(&mut self, cx: &mut Cx, _apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
|
||||||
|
// let tags = ["test1", "test2", "test3"];
|
||||||
|
self.items.clear();
|
||||||
|
for (i, title_text) in self.indicator_titles.iter().enumerate() {
|
||||||
|
// for (i, title_text) in tags.iter().enumerate() {
|
||||||
|
let item_id = LiveId::from_str(&format!("items{}", i));
|
||||||
|
let item_widget = WidgetRef::new_from_ptr(cx, self.template);
|
||||||
|
// item_widget.apply_over(cx, live! {label = { text: (title_text) }});
|
||||||
|
item_widget.apply_over(cx, live! {text: (title_text) });
|
||||||
|
self.items.insert(item_id, item_widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Indicators {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
for (_id, item) in self.items.iter_mut() {
|
||||||
|
item.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
cx.begin_turtle(walk, self.layout);
|
||||||
|
//Indicators
|
||||||
|
for (_id, item) in self.items.iter_mut() {
|
||||||
|
let _ = item.draw_all(cx, scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
cx.end_turtle_with_area(&mut self.draw_bg.draw_vars.area);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for Steps {
|
||||||
|
// fn after_new_from_doc(&mut self, cx: &mut Cx) {
|
||||||
|
fn after_apply(&mut self, cx: &mut Cx, _apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
|
||||||
|
for (idx, title_text) in self.page_titles.iter().enumerate() {
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", idx));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.page_template)
|
||||||
|
});
|
||||||
|
|
||||||
|
page.label(id!(step_title))
|
||||||
|
.set_text_and_redraw(cx, &format!("{}", &title_text.as_str()))
|
||||||
|
}
|
||||||
|
for (idx, title_text_vec) in self.choices_values.iter().enumerate() {
|
||||||
|
log!("Options: {:?}", &title_text_vec);
|
||||||
|
for (_idx, title_text) in title_text_vec.iter().enumerate() {
|
||||||
|
log!("Options: {:?}", &title_text);
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", idx));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.page_template)
|
||||||
|
});
|
||||||
|
page.button(id!(but))
|
||||||
|
.set_text_and_redraw(cx, &format!("{}", &title_text.as_str()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Steps {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, _scope: &mut Scope) {
|
||||||
|
// //Options
|
||||||
|
// for (_id, item) in self.items.iter_mut() {
|
||||||
|
// item.handle_event(cx, event, scope);
|
||||||
|
// }
|
||||||
|
if self.animator_handle_event(cx, event).must_redraw() {
|
||||||
|
self.redraw(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fire the "show" animation when the "restart" animation is done
|
||||||
|
if self.animator.animator_in_state(cx, id!(choice.restart)) {
|
||||||
|
self.animator_play(cx, id!(choice.show));
|
||||||
|
}
|
||||||
|
|
||||||
|
match event.hits(cx, self.draw_bg.draw_vars.area) {
|
||||||
|
Hit::FingerUp(fe) => {
|
||||||
|
if fe.is_over {
|
||||||
|
// Do not fire a new animation if the choice is already animating
|
||||||
|
if !self.animator.is_track_animating(cx, id!(choice)) {
|
||||||
|
self.update_current_page();
|
||||||
|
self.animator_play(cx, id!(choice.restart));
|
||||||
|
//self.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// fn redraw(&mut self, cx: &mut Cx) {
|
||||||
|
// self.area.redraw(cx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
// let walk = self.walk(cx);
|
||||||
|
self.draw_walkd(cx, scope, walk);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Steps {
|
||||||
|
fn draw_walkd(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) {
|
||||||
|
cx.begin_turtle(walk, Layout::default());
|
||||||
|
|
||||||
|
self.draw_page_with_offset(cx, scope, self.current_page, self.choice_page_offset, walk);
|
||||||
|
|
||||||
|
let prev_page_idx =
|
||||||
|
(self.current_page + self.page_titles.len() as u8 - 1) % self.page_titles.len() as u8;
|
||||||
|
self.draw_page_with_offset(
|
||||||
|
cx,
|
||||||
|
scope,
|
||||||
|
prev_page_idx,
|
||||||
|
self.choice_page_offset - CHOICE_MAX_OFFSET,
|
||||||
|
walk,
|
||||||
|
);
|
||||||
|
|
||||||
|
cx.end_turtle_with_area(&mut self.draw_bg.draw_vars.area);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_page_with_offset(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx2d,
|
||||||
|
scope: &mut Scope,
|
||||||
|
index: u8,
|
||||||
|
offset: f64,
|
||||||
|
walk: Walk,
|
||||||
|
) {
|
||||||
|
let widget_id = LiveId::from_str(&format!("page{}", index));
|
||||||
|
let page = self.pages.get_or_insert(cx, widget_id, |cx| {
|
||||||
|
WidgetRef::new_from_ptr(cx, self.page_template)
|
||||||
|
});
|
||||||
|
|
||||||
|
let _ = page.draw_walk(cx, scope, walk.with_margin_left(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_current_page(&mut self) {
|
||||||
|
self.current_page = (self.current_page + 1) % self.page_titles.len() as u8;
|
||||||
|
// self.current_page = (self.current_page + 1) % self.choices_values.len() as u8;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,5 @@
|
||||||
use makepad_widgets::widget::WidgetCache;
|
use makepad_widgets::widget::WidgetCache;
|
||||||
use makepad_widgets::*;
|
use makepad_widgets::*;
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
// use crate::shared::steps::StepsNavSetWidgetExt;
|
|
||||||
|
|
||||||
live_design! {
|
live_design! {
|
||||||
import makepad_draw::shader::std::*;
|
import makepad_draw::shader::std::*;
|
||||||
|
@ -11,49 +8,207 @@ live_design! {
|
||||||
|
|
||||||
import crate::shared::styles::*;
|
import crate::shared::styles::*;
|
||||||
import crate::shared::custom_button::CustomButton;
|
import crate::shared::custom_button::CustomButton;
|
||||||
|
import crate::shared::round_slider::RoundSlider;
|
||||||
|
// import crate::default_choice::choose::Choose;Choose
|
||||||
|
import crate::default_choice::choice::Choose;
|
||||||
|
|
||||||
DefaultChoiceScreen = <View> {
|
|
||||||
|
StepOneScreen = <View> {
|
||||||
|
flow: Down,
|
||||||
|
spacing: (SSPACING_2),
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
label = <Label> {
|
||||||
|
margin: {top: 1}
|
||||||
|
draw_text: {
|
||||||
|
text_style: <H2_TEXT_BOLD> {},
|
||||||
|
color: (COLOR_DOWN_6)
|
||||||
|
}
|
||||||
|
text: "Step One"
|
||||||
|
}
|
||||||
|
getstarted = <CustomButton> {
|
||||||
|
width: 250
|
||||||
|
height: Fit
|
||||||
|
text: "Submit"
|
||||||
|
draw_bg: {
|
||||||
|
border_radius: 2.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getstartedw = <CustomButton> {
|
||||||
|
width: 250
|
||||||
|
height: Fit
|
||||||
|
text: "Submit"
|
||||||
|
draw_bg: {
|
||||||
|
border_radius: 2.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StepTwoScreen = <View> {
|
||||||
|
flow: Down, spacing: (SSPACING_2),
|
||||||
|
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
label = <Label> {
|
||||||
|
margin: {top: 1}
|
||||||
|
draw_text: {
|
||||||
|
text_style: <H2_TEXT_BOLD> {},
|
||||||
|
color: (COLOR_DOWN_6)
|
||||||
|
}
|
||||||
|
text: "Step Two"
|
||||||
|
}
|
||||||
|
getstarted = <CustomButton> {
|
||||||
|
width: 250
|
||||||
|
height: Fit
|
||||||
|
text: "Submit"
|
||||||
|
draw_bg: {
|
||||||
|
border_radius: 2.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StepThreeScreen = <View> {
|
||||||
|
flow: Down, spacing: (SSPACING_2),
|
||||||
|
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
label = <Label> {
|
||||||
|
margin: {top: 1}
|
||||||
|
draw_text: {
|
||||||
|
text_style: <H2_TEXT_BOLD> {},
|
||||||
|
color: (COLOR_DOWN_6)
|
||||||
|
}
|
||||||
|
text: "Step Three"
|
||||||
|
}
|
||||||
|
getstarted = <CustomButton> {
|
||||||
|
width: 250
|
||||||
|
height: Fit
|
||||||
|
text: "Submit"
|
||||||
|
draw_bg: {
|
||||||
|
border_radius: 2.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FishHeader = <RoundedView> {
|
||||||
|
flow: Right
|
||||||
|
height: Fit,
|
||||||
|
width: Fill,
|
||||||
|
margin: {bottom: (SSPACING_2)}
|
||||||
|
align: {x: 1.0, y: 0.5},
|
||||||
|
// flow: Right,
|
||||||
|
// spacing: 5.,
|
||||||
|
padding: {right: 5.}
|
||||||
|
|
||||||
|
|
||||||
|
// title = <FishTitle> {
|
||||||
|
// height: Fit,
|
||||||
|
// width: Fill,
|
||||||
|
// margin: <SPACING_0> {}
|
||||||
|
// padding: <SPACING_2> {}
|
||||||
|
// }
|
||||||
|
menu = <DropDown> {//DropDown NavBar
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Indicator = <RoundedView> {
|
||||||
|
width: 100.0
|
||||||
|
height: 8.0
|
||||||
|
draw_bg: {
|
||||||
|
color: #f60,
|
||||||
|
radius: 2.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DefaultChoiceScreen = {{DefaultChoiceScreen}} {
|
||||||
|
width: Fit,
|
||||||
|
height: Fit,
|
||||||
|
flow: Right,
|
||||||
|
spacing: 5,
|
||||||
|
|
||||||
|
template: <CheckBox> {}
|
||||||
|
// template: <Indicator> {}
|
||||||
|
}
|
||||||
|
DefaultChoice = <View> {
|
||||||
width: Fill, height: Fill flow: Down
|
width: Fill, height: Fill flow: Down
|
||||||
<View> {
|
<View> {
|
||||||
flow: Down,
|
flow: Down,
|
||||||
align: {x: 0.5, y: 0.3}
|
align: {x: 0.5, y: 0.3}
|
||||||
<View> {
|
// <ModelFilesTags>{}
|
||||||
flow: Down,
|
// // <DefaultChoiceScreen>{}
|
||||||
spacing: (SSPACING_2),
|
|
||||||
align: {x: 0.5, y: 0.5}
|
<View> {
|
||||||
label = <Label> {
|
flow: Down,
|
||||||
margin: {top: 1}
|
spacing: (SSPACING_2),
|
||||||
draw_text: {
|
align: {x: 0.5, y: 0.5}
|
||||||
text_style: <H2_TEXT_BOLD> {},
|
|
||||||
color: (COLOR_DOWN_6)
|
// <DefaultChoiceScreen>{}
|
||||||
}
|
Choose = <Choose> {}
|
||||||
text: "Step One"
|
// <View> {
|
||||||
}
|
// debug: M
|
||||||
getstarted = <CustomButton> {
|
// width: 300, height: 150
|
||||||
width: 250
|
// align: {x: 0.5, y: 0.5}
|
||||||
height: Fit
|
// <RoundSlider> {}
|
||||||
text: "Submit"
|
// }
|
||||||
draw_bg: {
|
|
||||||
border_radius: 2.
|
// label = <Label> {
|
||||||
}
|
// margin: {top: 1}
|
||||||
}
|
// draw_text: {
|
||||||
getstartedw = <CustomButton> {
|
// text_style: <H2_TEXT_BOLD> {},
|
||||||
width: 250
|
// color: (COLOR_DOWN_6)
|
||||||
height: Fit
|
// }
|
||||||
text: "Submit"
|
// text: "Step One"
|
||||||
draw_bg: {
|
// }
|
||||||
border_radius: 2.
|
// getstarted = <CustomButton> {
|
||||||
}
|
// width: 250
|
||||||
}
|
// height: Fit
|
||||||
}
|
// text: "Submit"
|
||||||
|
// draw_bg: {
|
||||||
|
// border_radius: 2.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// getstartedw = <CustomButton> {
|
||||||
|
// width: 250
|
||||||
|
// height: Fit
|
||||||
|
// text: "Submit"
|
||||||
|
// draw_bg: {
|
||||||
|
// border_radius: 2.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Live, LiveHook, Widget)]
|
#[derive(Live, Widget)]
|
||||||
pub struct DefaultChoiceScreen {
|
pub struct DefaultChoiceScreen {
|
||||||
#[deref]
|
#[deref]
|
||||||
view: View,
|
view: View,
|
||||||
|
|
||||||
|
#[redraw]
|
||||||
|
#[rust]
|
||||||
|
area: Area,
|
||||||
|
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
items: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for DefaultChoiceScreen {
|
||||||
|
fn after_apply(&mut self, cx: &mut Cx, _apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
|
||||||
|
let tags = ["test1", "test2", "test3"];
|
||||||
|
|
||||||
|
self.items.clear();
|
||||||
|
for (i, tag) in tags.iter().enumerate() {
|
||||||
|
let item_id = LiveId(i as u64).into();
|
||||||
|
let item_widget = WidgetRef::new_from_ptr(cx, self.template);
|
||||||
|
item_widget.apply_over(cx, live! {label = { text: (tag) }});
|
||||||
|
self.items.insert(item_id, item_widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for DefaultChoiceScreen {
|
impl Widget for DefaultChoiceScreen {
|
||||||
|
@ -64,9 +219,17 @@ impl Widget for DefaultChoiceScreen {
|
||||||
if self.view.button(id!(getstartedw)).clicked(&actions) {
|
if self.view.button(id!(getstartedw)).clicked(&actions) {
|
||||||
log!("Option Selected: {}", 0);
|
log!("Option Selected: {}", 0);
|
||||||
}
|
}
|
||||||
|
for (_id, item) in self.items.iter_mut() {
|
||||||
|
item.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
self.view.draw_walk(cx, scope, walk)
|
cx.begin_turtle(walk, self.layout);
|
||||||
|
for (_id, item) in self.items.iter_mut() {
|
||||||
|
let _ = item.draw_all(cx, scope);
|
||||||
|
}
|
||||||
|
cx.end_turtle_with_area(&mut self.area);
|
||||||
|
DrawStep::done()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
|
pub mod choice;
|
||||||
|
// pub mod choose;
|
||||||
pub mod default_choice_screen;
|
pub mod default_choice_screen;
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use crate::utils::get_current_year;
|
use crate::utils::get_current_year;
|
||||||
|
|
||||||
|
// #[cfg(target_arch = "wasm32")]
|
||||||
|
// use crate::utils::get_current_year;
|
||||||
|
|
||||||
use makepad_widgets::*;
|
use makepad_widgets::*;
|
||||||
|
|
||||||
live_design! {
|
live_design! {
|
||||||
|
@ -146,9 +150,13 @@ impl Widget for Home {
|
||||||
|
|
||||||
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
let label = self.view.label(id!(footer));
|
let label = self.view.label(id!(footer));
|
||||||
|
// let check_box = self.view.check_box(id!(footer));
|
||||||
// NiManyatta © 2024
|
// NiManyatta © 2024
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
let year = get_current_year();
|
let year = get_current_year();
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
label.set_text_and_redraw(cx, &format!("NiManyatta © {}", year));
|
label.set_text_and_redraw(cx, &format!("NiManyatta © {}", year));
|
||||||
|
// check_box.set_text_and_redraw(cx, &format!("NiManyatta © {}", year));
|
||||||
self.view.draw_walk(cx, scope, walk)
|
self.view.draw_walk(cx, scope, walk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
43
nimanyatta_v001/src/index.html
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta
|
||||||
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, user-scalable=no"
|
||||||
|
/>
|
||||||
|
<title>Simple</title>
|
||||||
|
<script type="module">
|
||||||
|
import { WasmWebGL } from "../../makepad/platform/src/os/web/web_gl.js";
|
||||||
|
|
||||||
|
const wasm = await WasmWebGL.fetch_and_instantiate_wasm(
|
||||||
|
"/nimanyatta_v001/target/wasm32-unknown-unknown/release/nimanyatta_v001.wasm",
|
||||||
|
);
|
||||||
|
|
||||||
|
class MyWasmApp {
|
||||||
|
constructor(wasm) {
|
||||||
|
let canvas =
|
||||||
|
document.getElementsByClassName("full_canvas")[0];
|
||||||
|
this.webgl = new WasmWebGL(wasm, this, canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let app = new MyWasmApp(wasm);
|
||||||
|
</script>
|
||||||
|
<script
|
||||||
|
type="module"
|
||||||
|
src="../../makepad/platform/src/os/web/auto_reload.js"
|
||||||
|
></script>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
type="text/css"
|
||||||
|
href="../../makepad/platform/src/os/web/full_canvas.css"
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<canvas class="full_canvas"></canvas>
|
||||||
|
<div class="canvas_loader">
|
||||||
|
<div style="">Loading..</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -7,4 +7,6 @@ pub mod home;
|
||||||
pub mod shared;
|
pub mod shared;
|
||||||
pub mod three;
|
pub mod three;
|
||||||
pub mod two;
|
pub mod two;
|
||||||
|
|
||||||
|
// #[cfg(not(target_arch = "wasm32"))]
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
6
nimanyatta_v001/src/options.json
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"Help Me Choose": {},
|
||||||
|
"Help Me Build": {
|
||||||
|
"Help Me Build": {}
|
||||||
|
}
|
||||||
|
}
|
483
nimanyatta_v001/src/shared/cho.rs
Normal file
|
@ -0,0 +1,483 @@
|
||||||
|
use makepad_widgets::*;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_draw::shader::std::*;
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
|
||||||
|
DrawStepsNav = {{DrawStepsNav}} {}
|
||||||
|
StepsNavBase = {{StepsNav}} {}
|
||||||
|
StepNav = <StepsNavBase> {
|
||||||
|
|
||||||
|
width: Fit,
|
||||||
|
height: Fit
|
||||||
|
|
||||||
|
label_walk: {
|
||||||
|
margin: {left: 20.0, top: 8, bottom: 8, right: 10}
|
||||||
|
width: Fit,
|
||||||
|
height: Fit,
|
||||||
|
}
|
||||||
|
|
||||||
|
label_align: {
|
||||||
|
y: 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_check: {
|
||||||
|
uniform size: 7.0;
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
match self.check_type {
|
||||||
|
CheckType::Check => {
|
||||||
|
let left = 3;
|
||||||
|
let sz = self.size;
|
||||||
|
let c = vec2(left + sz, self.rect_size.y * 0.5);
|
||||||
|
sdf.box(left, c.y - sz, sz * 2.0, sz * 2.0, 3.0); // rounding = 3rd value
|
||||||
|
sdf.fill_keep(mix(mix(#x00000077, #x00000044, pow(self.pos.y, 1.)), mix(#x000000AA, #x00000066, pow(self.pos.y, 1.0)), self.hover))
|
||||||
|
sdf.stroke(#x888, 1.0) // outline
|
||||||
|
let szs = sz * 0.5;
|
||||||
|
let dx = 1.0;
|
||||||
|
sdf.move_to(left + 4.0, c.y);
|
||||||
|
sdf.line_to(c.x, c.y + szs);
|
||||||
|
sdf.line_to(c.x + szs, c.y - szs);
|
||||||
|
sdf.stroke(mix(#fff0, #f, self.selected), 1.25);
|
||||||
|
}
|
||||||
|
CheckType::Radio => {
|
||||||
|
let sz = self.size;
|
||||||
|
let left = sz + 1.;
|
||||||
|
let c = vec2(left + sz, self.rect_size.y * 0.5);
|
||||||
|
sdf.circle(left, c.y, sz);
|
||||||
|
sdf.fill(#2);
|
||||||
|
let isz = sz * 0.5;
|
||||||
|
sdf.circle(left, c.y, isz);
|
||||||
|
sdf.fill(mix(#fff0, #f, self.selected));
|
||||||
|
}
|
||||||
|
CheckType::Toggle => {
|
||||||
|
let sz = self.size;
|
||||||
|
let left = sz + 1.;
|
||||||
|
let c = vec2(left + sz, self.rect_size.y * 0.5);
|
||||||
|
sdf.box(left, c.y - sz, sz * 3.0, sz * 2.0, 0.5 * sz);
|
||||||
|
sdf.fill(#2);
|
||||||
|
let isz = sz * 0.5;
|
||||||
|
sdf.circle(left + sz + self.selected * sz, c.y, isz);
|
||||||
|
sdf.circle(left + sz + self.selected * sz, c.y, 0.5 * isz);
|
||||||
|
sdf.subtract();
|
||||||
|
sdf.circle(left + sz + self.selected * sz, c.y, isz);
|
||||||
|
sdf.blend(self.selected)
|
||||||
|
sdf.fill(#f);
|
||||||
|
}
|
||||||
|
CheckType::None => {
|
||||||
|
return #0000
|
||||||
|
}
|
||||||
|
CheckType::Bar => {
|
||||||
|
let sz = self.size;
|
||||||
|
let left = sz + 1.;
|
||||||
|
let up = sz + 3.5;
|
||||||
|
let c = self.rect_size * vec2(0.5, 0.5);
|
||||||
|
sdf.box(
|
||||||
|
left,
|
||||||
|
c.y - up,
|
||||||
|
12. * sz + 5,
|
||||||
|
1. * sz,
|
||||||
|
1.9
|
||||||
|
);
|
||||||
|
|
||||||
|
sdf.fill(#232323);
|
||||||
|
sdf.stroke(#000, 0.5 + 0.5 * self.dpi_dilate);
|
||||||
|
|
||||||
|
let isz = sz * 0.5;
|
||||||
|
let ileft = isz + 4.5;
|
||||||
|
let iup = sz + 3.5;
|
||||||
|
sdf.box(
|
||||||
|
ileft,
|
||||||
|
c.y - iup,
|
||||||
|
12. * sz + 5,
|
||||||
|
1. * sz,
|
||||||
|
1.9
|
||||||
|
);
|
||||||
|
sdf.fill(mix(#fff0, #016def, self.selected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_text: {
|
||||||
|
color: #9,
|
||||||
|
instance focus: 0.0
|
||||||
|
instance selected: 0.0
|
||||||
|
instance hover: 0.0
|
||||||
|
text_style: {
|
||||||
|
font: {
|
||||||
|
//path: d"resources/IBMPlexSans-SemiBold.ttf"
|
||||||
|
}
|
||||||
|
font_size: 11.0
|
||||||
|
}
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
#fff6,
|
||||||
|
#fff6,
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
#fff6,
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_icon: {
|
||||||
|
instance focus: 0.0
|
||||||
|
instance hover: 0.0
|
||||||
|
instance selected: 0.0
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
#9,
|
||||||
|
#c,
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
#f,
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
animator: {
|
||||||
|
hover = {
|
||||||
|
default: off
|
||||||
|
off = {
|
||||||
|
from: {all: Forward {duration: 0.15}}
|
||||||
|
apply: {
|
||||||
|
draw_check: {hover: 0.0}
|
||||||
|
draw_text: {hover: 0.0}
|
||||||
|
draw_icon: {hover: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
on = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {
|
||||||
|
draw_check: {hover: 1.0}
|
||||||
|
draw_text: {hover: 1.0}
|
||||||
|
draw_icon: {hover: 1.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
focus = {
|
||||||
|
default: off
|
||||||
|
off = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {
|
||||||
|
draw_check: {focus: 0.0}
|
||||||
|
draw_text: {focus: 0.0}
|
||||||
|
draw_icon: {focus: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
on = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {
|
||||||
|
draw_check: {focus: 1.0}
|
||||||
|
draw_text: {focus: 1.0}
|
||||||
|
draw_icon: {focus: 1.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selected = {
|
||||||
|
default: off
|
||||||
|
off = {
|
||||||
|
from: {all: Forward {duration: 0.1}}
|
||||||
|
apply: {
|
||||||
|
draw_check: {selected: 0.0},
|
||||||
|
draw_text: {selected: 0.0},
|
||||||
|
draw_icon: {selected: 0.0},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
on = {
|
||||||
|
from: {all: Forward {duration: 0.0}}
|
||||||
|
apply: {
|
||||||
|
draw_check: {selected: 1.0}
|
||||||
|
draw_text: {selected: 1.0}
|
||||||
|
draw_icon: {selected: 1.0},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Cho = <StepNav>{
|
||||||
|
width: 100, height: 20,
|
||||||
|
margin: 0, padding: 0
|
||||||
|
flow: Right,
|
||||||
|
align: {x: 0.5, y: 0.5},
|
||||||
|
draw_check: {
|
||||||
|
check_type: Bar,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// CheckContainer = <View> {
|
||||||
|
// width: Fit,
|
||||||
|
// height: Fit,
|
||||||
|
// checkbox = <CheckBox> {
|
||||||
|
// width: 400
|
||||||
|
// height: 266
|
||||||
|
// text: "Check me out!"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
ModelFilesTags = {{ModelFilesTags}} {
|
||||||
|
width: Fit,
|
||||||
|
height: Fit,
|
||||||
|
flow: Right,
|
||||||
|
spacing: 5,
|
||||||
|
|
||||||
|
template: <Cho> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[derive(Live, Widget)]
|
||||||
|
// pub struct Choices {
|
||||||
|
// #[redraw]
|
||||||
|
// #[live]
|
||||||
|
// steps: ScrollBars,
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[derive(Live, LiveHook, Widget)]
|
||||||
|
pub struct ModelFilesTags {
|
||||||
|
#[redraw]
|
||||||
|
#[rust]
|
||||||
|
area: Area,
|
||||||
|
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
template: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
items: ComponentMap<LiveId, WidgetRef>,
|
||||||
|
}
|
||||||
|
// impl LiveHook for ModelFilesTags {
|
||||||
|
// fn after_apply(&mut self, _cx: &mut Cx, _apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
|
||||||
|
// self.set_tags
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
impl Widget for ModelFilesTags {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
for (_id, item) in self.items.iter_mut() {
|
||||||
|
item.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
cx.begin_turtle(walk, self.layout);
|
||||||
|
for (_id, item) in self.items.iter_mut() {
|
||||||
|
let _ = item.draw_walk(cx, scope, walk);
|
||||||
|
}
|
||||||
|
cx.end_turtle_with_area(&mut self.area);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// impl LiveHook for ModelFilesTags {
|
||||||
|
// fn before_live_design(cx: &mut Cx) {
|
||||||
|
// register_widget!(cx, ModelFilesTags);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
impl ModelFilesTagsRef {
|
||||||
|
pub fn set_tags(&self, cx: &mut Cx, tags: Vec<String>) {
|
||||||
|
let Some(mut tags_widget) = self.borrow_mut() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
tags_widget.items.clear();
|
||||||
|
for (i, tag) in tags.iter().enumerate() {
|
||||||
|
let item_id = LiveId(i as u64).into();
|
||||||
|
let item_widget = WidgetRef::new_from_ptr(cx, tags_widget.template);
|
||||||
|
item_widget.apply_over(cx, live! {label = { text: (tag) }});
|
||||||
|
tags_widget.items.insert(item_id, item_widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Live, LiveHook, LiveRegister)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct DrawStepsNav {
|
||||||
|
#[deref]
|
||||||
|
draw_super: DrawQuad,
|
||||||
|
#[live]
|
||||||
|
check_type: CheckType,
|
||||||
|
#[live]
|
||||||
|
hover: f32,
|
||||||
|
#[live]
|
||||||
|
focus: f32,
|
||||||
|
#[live]
|
||||||
|
selected: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, LiveHook, Widget)]
|
||||||
|
pub struct StepsNav {
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
icon_walk: Walk,
|
||||||
|
#[live]
|
||||||
|
label_walk: Walk, //
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_name: DrawText, //
|
||||||
|
#[live]
|
||||||
|
label_align: Align, //
|
||||||
|
|
||||||
|
#[redraw]
|
||||||
|
#[live]
|
||||||
|
draw_check: DrawStepsNav, //
|
||||||
|
#[live]
|
||||||
|
draw_text: DrawText,
|
||||||
|
#[live]
|
||||||
|
draw_icon: DrawIcon,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
text: RcStringMut, //
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
bind: String, //
|
||||||
|
}
|
||||||
|
#[derive(Live, LiveHook, LiveRegister)]
|
||||||
|
#[live_ignore]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum CheckType {
|
||||||
|
#[pick]
|
||||||
|
Check = shader_enum(1),
|
||||||
|
Radio = shader_enum(2),
|
||||||
|
Toggle = shader_enum(3),
|
||||||
|
None = shader_enum(4),
|
||||||
|
Bar = shader_enum(5), //RadioType::Bar
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Debug)]
|
||||||
|
pub enum StepsNavAction {
|
||||||
|
Change(bool),
|
||||||
|
WasSweeped,
|
||||||
|
WasSelected,
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
impl StepsNav {
|
||||||
|
pub fn draw_walk(&mut self, cx: &mut Cx2d, walk: Walk) {
|
||||||
|
self.draw_check.begin(cx, walk, self.layout);
|
||||||
|
// self.draw_icon.svg_file = icon;
|
||||||
|
|
||||||
|
self.draw_text
|
||||||
|
.draw_walk(cx, self.label_walk, self.label_align, self.text.as_ref());
|
||||||
|
self.draw_icon.draw_walk(cx, self.icon_walk);
|
||||||
|
self.draw_check.end(cx);
|
||||||
|
}
|
||||||
|
pub fn handle_event_with(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx,
|
||||||
|
event: &Event,
|
||||||
|
sweep_area: Area,
|
||||||
|
dispatch_action: &mut dyn FnMut(&mut Cx, StepsNavAction),
|
||||||
|
) {
|
||||||
|
if self.animator_handle_event(cx, event).must_redraw() {
|
||||||
|
// self.draw_bg.area().redraw(cx);
|
||||||
|
self.draw_check.area().redraw(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
match event.hits_with_options(
|
||||||
|
cx,
|
||||||
|
// self.draw_bg.area(),
|
||||||
|
self.draw_check.area(),
|
||||||
|
HitOptions::new().with_sweep_area(sweep_area),
|
||||||
|
) {
|
||||||
|
Hit::FingerHoverIn(_) => {
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
}
|
||||||
|
Hit::FingerHoverOut(_) => {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
Hit::FingerDown(_) => {
|
||||||
|
dispatch_action(cx, StepsNavAction::WasSweeped);
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
self.animator_play(cx, id!(select.on));
|
||||||
|
}
|
||||||
|
Hit::FingerUp(se) => {
|
||||||
|
if !se.is_sweep {
|
||||||
|
dispatch_action(cx, StepsNavAction::WasSelected);
|
||||||
|
} else {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
self.animator_play(cx, id!(select.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for StepsNav {
|
||||||
|
fn widget_to_data(
|
||||||
|
&self,
|
||||||
|
_cx: &mut Cx,
|
||||||
|
actions: &Actions,
|
||||||
|
nodes: &mut LiveNodeVec,
|
||||||
|
path: &[LiveId],
|
||||||
|
) -> bool {
|
||||||
|
match actions.find_widget_action_cast(self.widget_uid()) {
|
||||||
|
StepsNavAction::Change(v) => {
|
||||||
|
nodes.write_field_value(path, LiveValue::Bool(v));
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_to_widget(&mut self, cx: &mut Cx, nodes: &[LiveNode], path: &[LiveId]) {
|
||||||
|
if let Some(value) = nodes.read_field_value(path) {
|
||||||
|
if let Some(value) = value.as_bool() {
|
||||||
|
self.animator_toggle(cx, value, Animate::Yes, id!(selected.on), id!(selected.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
let uid = self.widget_uid();
|
||||||
|
self.animator_handle_event(cx, event);
|
||||||
|
|
||||||
|
match event.hits(cx, self.draw_check.area()) {
|
||||||
|
Hit::FingerHoverIn(_) => {
|
||||||
|
cx.set_cursor(MouseCursor::Hand);
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
}
|
||||||
|
Hit::FingerHoverOut(_) => {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
Hit::FingerDown(_fe) => {
|
||||||
|
if self.animator_in_state(cx, id!(selected.on)) {
|
||||||
|
self.animator_play(cx, id!(selected.off));
|
||||||
|
cx.widget_action(uid, &scope.path, StepsNavAction::Change(false));
|
||||||
|
} else {
|
||||||
|
self.animator_play(cx, id!(selected.on));
|
||||||
|
cx.widget_action(uid, &scope.path, StepsNavAction::Change(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Hit::FingerUp(_fe) => {}
|
||||||
|
Hit::FingerMove(_fe) => {}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
self.draw_walk(cx, walk);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn text(&self) -> String {
|
||||||
|
self.text.as_ref().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_text(&mut self, v: &str) {
|
||||||
|
self.text.as_mut_empty().push_str(v);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
use makepad_widgets::*;
|
use makepad_widgets::{makepad_derive_widget::*, makepad_draw::*, widget::*};
|
||||||
|
|
||||||
live_design! {
|
live_design! {
|
||||||
import makepad_draw::shader::std::*;
|
import makepad_draw::shader::std::*;
|
||||||
|
@ -20,8 +20,8 @@ live_design! {
|
||||||
draw_bg: {
|
draw_bg: {
|
||||||
border_radius: 8.
|
border_radius: 8.
|
||||||
fn pixel(self) -> vec4 {
|
fn pixel(self) -> vec4 {
|
||||||
let border_color = #0157c0;
|
|
||||||
// let border_color = #016def; //#0157c0
|
// let border_color = #016def; //#0157c0
|
||||||
|
let border_color = #0157c0;
|
||||||
let border_width = 0.5;
|
let border_width = 0.5;
|
||||||
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
|
||||||
let body = mix(mix(#f, #0157c0, self.hover), #d1, self.pressed);
|
let body = mix(mix(#f, #0157c0, self.hover), #d1, self.pressed);
|
||||||
|
@ -43,4 +43,225 @@ live_design! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CustomButtonC = {{CustomButton}} {
|
||||||
|
// draw_cbutt: {
|
||||||
|
// <CustomButton>{}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// #[derive(Live, LiveHook, LiveRegister)]
|
||||||
|
// #[repr(C)]
|
||||||
|
// pub struct DrawCButton {
|
||||||
|
// #[deref]
|
||||||
|
// draw_super: DrawQuad,
|
||||||
|
// #[live]
|
||||||
|
// button_type: CButtonType,
|
||||||
|
// #[live]
|
||||||
|
// hover: f32,
|
||||||
|
// #[live]
|
||||||
|
// focus: f32,
|
||||||
|
// #[live]
|
||||||
|
// selected: f32,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[derive(Live, LiveHook)]
|
||||||
|
// #[live_ignore]
|
||||||
|
// #[repr(u32)]
|
||||||
|
// pub enum CButtonType {
|
||||||
|
// #[pick]
|
||||||
|
// Primary = shader_enum(1),
|
||||||
|
// Secondary = shader_enum(2),
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[derive(Live, LiveHook, Widget)]
|
||||||
|
// pub struct CustomButton {
|
||||||
|
// #[redraw]
|
||||||
|
// #[live]
|
||||||
|
// draw_cbtn: DrawCButton,
|
||||||
|
// }
|
||||||
|
// #[derive(Live, LiveHook, Widget)]
|
||||||
|
// pub struct CustomButton {
|
||||||
|
// #[walk]
|
||||||
|
// walk: Walk,
|
||||||
|
// #[layout]
|
||||||
|
// layout: Layout,
|
||||||
|
// #[animator]
|
||||||
|
// animator: Animator,
|
||||||
|
|
||||||
|
// #[live]
|
||||||
|
// icon_walk: Walk,
|
||||||
|
// #[live]
|
||||||
|
// label_walk: Walk,
|
||||||
|
// #[live]
|
||||||
|
// label_align: Align,
|
||||||
|
|
||||||
|
// // #[redraw]
|
||||||
|
// // #[live]
|
||||||
|
// // draw_check: DrawCheckBox,
|
||||||
|
// #[live]
|
||||||
|
// #[redraw]
|
||||||
|
// draw_cbutt: DrawCButton,
|
||||||
|
// #[live]
|
||||||
|
// draw_text: DrawText,
|
||||||
|
// #[live]
|
||||||
|
// draw_icon: DrawIcon,
|
||||||
|
|
||||||
|
// #[live]
|
||||||
|
// text: RcStringMut,
|
||||||
|
|
||||||
|
// #[live]
|
||||||
|
// bind: String,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[derive(Live, LiveHook, LiveRegister)]
|
||||||
|
// #[repr(C)]
|
||||||
|
// pub struct DrawCButton {
|
||||||
|
// #[deref]
|
||||||
|
// draw_super: DrawQuad,
|
||||||
|
// #[live]
|
||||||
|
// check_type: CButtonType,
|
||||||
|
// #[live]
|
||||||
|
// hover: f32,
|
||||||
|
// #[live]
|
||||||
|
// focus: f32,
|
||||||
|
// #[live]
|
||||||
|
// selected: f32,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[derive(Live, LiveHook, LiveRegister)]
|
||||||
|
// #[live_ignore]
|
||||||
|
// #[repr(u32)]
|
||||||
|
// pub enum CButtonType {
|
||||||
|
// #[pick]
|
||||||
|
// Clickable = shader_enum(1),
|
||||||
|
// UnClickable = shader_enum(2),
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[derive(Clone, Debug, DefaultNone)]
|
||||||
|
// pub enum CButtonBoxAction {
|
||||||
|
// Change(bool),
|
||||||
|
// None,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// #[derive(Live, LiveHook, LiveRegister)]
|
||||||
|
// #[repr(C)]
|
||||||
|
// struct DrawLabelText {
|
||||||
|
// #[deref]
|
||||||
|
// draw_super: DrawText,
|
||||||
|
// #[live]
|
||||||
|
// hover: f32,
|
||||||
|
// #[live]
|
||||||
|
// pressed: f32,
|
||||||
|
// }
|
||||||
|
// impl CustomButton {
|
||||||
|
// pub fn draw_walk(&mut self, cx: &mut Cx2d, walk: Walk) {
|
||||||
|
// self.draw_cbutt.begin(cx, walk, self.layout);
|
||||||
|
// self.draw_text
|
||||||
|
// .draw_walk(cx, self.label_walk, self.label_align, self.text.as_ref());
|
||||||
|
// self.draw_icon.draw_walk(cx, self.icon_walk);
|
||||||
|
// self.draw_cbutt.end(cx);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl Widget for CustomButton {
|
||||||
|
// fn widget_to_data(
|
||||||
|
// &self,
|
||||||
|
// _cx: &mut Cx,
|
||||||
|
// actions: &Actions,
|
||||||
|
// nodes: &mut LiveNodeVec,
|
||||||
|
// path: &[LiveId],
|
||||||
|
// ) -> bool {
|
||||||
|
// match actions.find_widget_action_cast(self.widget_uid()) {
|
||||||
|
// CButtonBoxAction::Change(v) => {
|
||||||
|
// nodes.write_field_value(path, LiveValue::Bool(v));
|
||||||
|
// true
|
||||||
|
// }
|
||||||
|
// _ => false,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn data_to_widget(&mut self, cx: &mut Cx, nodes: &[LiveNode], path: &[LiveId]) {
|
||||||
|
// if let Some(value) = nodes.read_field_value(path) {
|
||||||
|
// if let Some(value) = value.as_bool() {
|
||||||
|
// self.animator_toggle(cx, value, Animate::Yes, id!(selected.on), id!(selected.off));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
// let uid = self.widget_uid();
|
||||||
|
// self.animator_handle_event(cx, event);
|
||||||
|
|
||||||
|
// match event.hits(cx, self.draw_cbutt.area()) {
|
||||||
|
// Hit::FingerHoverIn(_) => {
|
||||||
|
// cx.set_cursor(MouseCursor::Hand);
|
||||||
|
// self.animator_play(cx, id!(hover.on));
|
||||||
|
// }
|
||||||
|
// Hit::FingerHoverOut(_) => {
|
||||||
|
// self.animator_play(cx, id!(hover.off));
|
||||||
|
// }
|
||||||
|
// Hit::FingerDown(_fe) => {
|
||||||
|
// if self.animator_in_state(cx, id!(selected.on)) {
|
||||||
|
// self.animator_play(cx, id!(selected.off));
|
||||||
|
// cx.widget_action(uid, &scope.path, CButtonBoxAction::Change(false));
|
||||||
|
// } else {
|
||||||
|
// self.animator_play(cx, id!(selected.on));
|
||||||
|
// cx.widget_action(uid, &scope.path, CButtonBoxAction::Change(true));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Hit::FingerUp(_fe) => {}
|
||||||
|
// Hit::FingerMove(_fe) => {}
|
||||||
|
// _ => (),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
// self.draw_walk(cx, walk);
|
||||||
|
// DrawStep::done()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn text(&self) -> String {
|
||||||
|
// self.text.as_ref().to_string()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn set_text(&mut self, v: &str) {
|
||||||
|
// self.text.as_mut_empty().push_str(v);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// impl CustomButtonRef {
|
||||||
|
// pub fn changed(&self, actions: &Actions) -> Option<bool> {
|
||||||
|
// if let CButtonBoxAction::Change(b) = actions.find_widget_action_cast(self.widget_uid()) {
|
||||||
|
// return Some(b);
|
||||||
|
// }
|
||||||
|
// None
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn set_text(&self, text: &str) {
|
||||||
|
// if let Some(mut inner) = self.borrow_mut() {
|
||||||
|
// let s = inner.text.as_mut_empty();
|
||||||
|
// s.push_str(text);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn selected(&self, cx: &Cx) -> bool {
|
||||||
|
// if let Some(inner) = self.borrow() {
|
||||||
|
// inner.animator_in_state(cx, id!(selected.on))
|
||||||
|
// } else {
|
||||||
|
// false
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub fn set_selected(&self, cx: &mut Cx, value: bool) {
|
||||||
|
// if let Some(mut inner) = self.borrow_mut() {
|
||||||
|
// inner.animator_toggle(cx, value, Animate::Yes, id!(selected.on), id!(selected.off));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // impl CustomButton {
|
||||||
|
// // pub fn area(&self) -> Area {
|
||||||
|
// // self.area
|
||||||
|
// // }
|
||||||
|
// // }
|
||||||
|
|
362
nimanyatta_v001/src/shared/dropdown_menu.rs
Normal file
|
@ -0,0 +1,362 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use makepad_widgets::makepad_derive_widget::*;
|
||||||
|
use makepad_widgets::makepad_draw::*;
|
||||||
|
use makepad_widgets::widget::*;
|
||||||
|
|
||||||
|
use crate::shared::popup_menu::*;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_draw::shader::std::*;
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
import crate::shared::popup_menu::*;
|
||||||
|
|
||||||
|
DropDown = {{WechatDropDown}} {
|
||||||
|
width: Fit,
|
||||||
|
height: Fit,
|
||||||
|
margin: {left: 1.0, right: 1.0, top: 1.0, bottom: 1.0},
|
||||||
|
align: {x: 0., y: 0.},
|
||||||
|
padding: {left: 5.0, top: 5.0, right: 4.0, bottom: 5.0}
|
||||||
|
|
||||||
|
draw_bg: {
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_icon: {
|
||||||
|
instance hover: 0.0
|
||||||
|
instance pressed: 0.0
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
#9,
|
||||||
|
#c,
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
#9,
|
||||||
|
self.pressed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
icon_walk: { width: 20., height: Fit}
|
||||||
|
|
||||||
|
popup_menu: <PopupMenu> {
|
||||||
|
}
|
||||||
|
|
||||||
|
popup_shift: vec2(-6.0,4.0)
|
||||||
|
|
||||||
|
selected_item: -1
|
||||||
|
animator: {
|
||||||
|
hover = {
|
||||||
|
default: off,
|
||||||
|
off = {
|
||||||
|
from: {all: Forward {duration: 0.1}}
|
||||||
|
apply: {
|
||||||
|
draw_icon: {pressed: 0.0, hover: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on = {
|
||||||
|
from: {
|
||||||
|
all: Forward {duration: 0.1}
|
||||||
|
pressed: Forward {duration: 0.01}
|
||||||
|
}
|
||||||
|
apply: {
|
||||||
|
draw_icon: {pressed: 0.0, hover: [{time: 0.0, value: 1.0}],}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pressed = {
|
||||||
|
from: {all: Forward {duration: 0.2}}
|
||||||
|
apply: {
|
||||||
|
draw_icon: {pressed: [{time: 0.0, value: 1.0}], hover: 1.0,}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct WechatDropDown {
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_bg: DrawQuad,
|
||||||
|
#[live]
|
||||||
|
draw_icon: DrawIcon,
|
||||||
|
#[live]
|
||||||
|
icon_walk: Walk,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
bind: String,
|
||||||
|
#[live]
|
||||||
|
bind_enum: String,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
popup_menu: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
labels: Vec<String>,
|
||||||
|
#[live]
|
||||||
|
values: Vec<LiveValue>,
|
||||||
|
#[live]
|
||||||
|
icons: Vec<LiveDependency>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
popup_shift: DVec2,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
is_open: bool,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
selected_item: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for WechatDropDown {
|
||||||
|
fn after_apply_from(&mut self, cx: &mut Cx, apply: &mut Apply) {
|
||||||
|
if self.popup_menu.is_none() || !apply.from.is_from_doc() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let global = cx.global::<PopupMenuGlobal>().clone();
|
||||||
|
let mut map = global.map.borrow_mut();
|
||||||
|
|
||||||
|
// when live styling clean up old style references
|
||||||
|
map.retain(|k, _| cx.live_registry.borrow().generation_valid(*k));
|
||||||
|
|
||||||
|
let list_box = self.popup_menu.unwrap();
|
||||||
|
map.get_or_insert(cx, list_box, |cx| {
|
||||||
|
PopupMenu::new_from_ptr(cx, Some(list_box))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Clone, DefaultNone, Debug)]
|
||||||
|
pub enum WechatDropDownAction {
|
||||||
|
Select(usize, LiveValue),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
struct PopupMenuGlobal {
|
||||||
|
map: Rc<RefCell<ComponentMap<LivePtr, PopupMenu>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WechatDropDown {
|
||||||
|
pub fn toggle_open(&mut self, cx: &mut Cx) {
|
||||||
|
if self.is_open {
|
||||||
|
self.set_closed(cx);
|
||||||
|
} else {
|
||||||
|
self.set_open(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_open(&mut self, cx: &mut Cx) {
|
||||||
|
self.is_open = true;
|
||||||
|
self.draw_bg.redraw(cx);
|
||||||
|
let global = cx.global::<PopupMenuGlobal>().clone();
|
||||||
|
let mut map = global.map.borrow_mut();
|
||||||
|
let lb = map.get_mut(&self.popup_menu.unwrap()).unwrap();
|
||||||
|
let node_id = LiveId(self.selected_item as u64).into();
|
||||||
|
lb.init_select_item(node_id);
|
||||||
|
cx.sweep_lock(self.draw_bg.area());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_closed(&mut self, cx: &mut Cx) {
|
||||||
|
self.is_open = false;
|
||||||
|
self.draw_bg.redraw(cx);
|
||||||
|
cx.sweep_unlock(self.draw_bg.area());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is named WechatDropDown because DropDown is already a widget in makepad_widgets
|
||||||
|
impl Widget for WechatDropDown {
|
||||||
|
fn widget_to_data(
|
||||||
|
&self,
|
||||||
|
_cx: &mut Cx,
|
||||||
|
actions: &Actions,
|
||||||
|
nodes: &mut LiveNodeVec,
|
||||||
|
path: &[LiveId],
|
||||||
|
) -> bool {
|
||||||
|
match actions.find_widget_action(self.widget_uid()).cast() {
|
||||||
|
WechatDropDownAction::Select(_, value) => {
|
||||||
|
nodes.write_field_value(path, value.clone());
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_to_widget(&mut self, cx: &mut Cx, nodes: &[LiveNode], path: &[LiveId]) {
|
||||||
|
if let Some(value) = nodes.read_field_value(path) {
|
||||||
|
if let Some(index) = self.values.iter().position(|v| v == value) {
|
||||||
|
if self.selected_item != index {
|
||||||
|
self.selected_item = index;
|
||||||
|
self.redraw(cx);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// error!("Value not in values list {:?}", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
self.animator_handle_event(cx, event);
|
||||||
|
let uid = self.widget_uid();
|
||||||
|
|
||||||
|
if self.is_open && self.popup_menu.is_some() {
|
||||||
|
let global = cx.global::<PopupMenuGlobal>().clone();
|
||||||
|
let mut map = global.map.borrow_mut();
|
||||||
|
let menu = map.get_mut(&self.popup_menu.unwrap()).unwrap();
|
||||||
|
let mut close = false;
|
||||||
|
menu.handle_event_with(cx, event, self.draw_bg.area(), &mut |cx, action| {
|
||||||
|
if let PopupMenuAction::WasSelected(node_id) = action {
|
||||||
|
self.selected_item = node_id.0 .0 as usize;
|
||||||
|
cx.widget_action(
|
||||||
|
uid,
|
||||||
|
&scope.path,
|
||||||
|
WechatDropDownAction::Select(
|
||||||
|
self.selected_item,
|
||||||
|
self.values
|
||||||
|
.get(self.selected_item)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(LiveValue::None),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
self.draw_bg.redraw(cx);
|
||||||
|
close = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if close {
|
||||||
|
self.set_closed(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we touch outside of the popup menu
|
||||||
|
if let Event::MouseDown(e) = event {
|
||||||
|
if !menu.menu_contains_pos(cx, e.abs) {
|
||||||
|
self.set_closed(cx);
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: close on clicking outside of the popup menu
|
||||||
|
match event.hits_with_sweep_area(cx, self.draw_bg.area(), self.draw_bg.area()) {
|
||||||
|
Hit::KeyFocusLost(_) => {
|
||||||
|
self.set_closed(cx);
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
self.draw_bg.redraw(cx);
|
||||||
|
}
|
||||||
|
Hit::KeyDown(ke) => match ke.key_code {
|
||||||
|
KeyCode::ArrowUp => {
|
||||||
|
if self.selected_item > 0 {
|
||||||
|
self.selected_item -= 1;
|
||||||
|
cx.widget_action(
|
||||||
|
uid,
|
||||||
|
&scope.path,
|
||||||
|
WechatDropDownAction::Select(
|
||||||
|
self.selected_item,
|
||||||
|
self.values
|
||||||
|
.get(self.selected_item)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(LiveValue::None),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
self.set_closed(cx);
|
||||||
|
self.draw_bg.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyCode::ArrowDown => {
|
||||||
|
if !self.values.is_empty() && self.selected_item < self.values.len() - 1 {
|
||||||
|
self.selected_item += 1;
|
||||||
|
cx.widget_action(
|
||||||
|
uid,
|
||||||
|
&scope.path,
|
||||||
|
WechatDropDownAction::Select(
|
||||||
|
self.selected_item,
|
||||||
|
self.values
|
||||||
|
.get(self.selected_item)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(LiveValue::None),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
self.set_closed(cx);
|
||||||
|
self.draw_bg.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
Hit::FingerDown(_fe) => {
|
||||||
|
cx.set_key_focus(self.draw_bg.area());
|
||||||
|
self.toggle_open(cx);
|
||||||
|
self.animator_play(cx, id!(hover.pressed));
|
||||||
|
}
|
||||||
|
Hit::FingerHoverIn(_) => {
|
||||||
|
cx.set_cursor(MouseCursor::Hand);
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
}
|
||||||
|
Hit::FingerHoverOut(_) => {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
Hit::FingerUp(fe) => {
|
||||||
|
if fe.is_over {
|
||||||
|
if fe.device.has_hovers() {
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
// cx.clear_sweep_lock(self.draw_bg.area());
|
||||||
|
|
||||||
|
self.draw_bg.begin(cx, walk, self.layout);
|
||||||
|
//let start_pos = cx.turtle().rect().pos;
|
||||||
|
self.draw_icon.draw_walk(cx, self.icon_walk);
|
||||||
|
self.draw_bg.end(cx);
|
||||||
|
|
||||||
|
cx.add_nav_stop(self.draw_bg.area(), NavRole::DropDown, Margin::default());
|
||||||
|
|
||||||
|
if self.is_open && self.popup_menu.is_some() {
|
||||||
|
// cx.set_sweep_lock(self.draw_bg.area());
|
||||||
|
let global = cx.global::<PopupMenuGlobal>().clone();
|
||||||
|
let mut map = global.map.borrow_mut();
|
||||||
|
let popup_menu = map.get_mut(&self.popup_menu.unwrap()).unwrap();
|
||||||
|
|
||||||
|
popup_menu.begin(cx);
|
||||||
|
|
||||||
|
for (i, item) in self.labels.iter().enumerate() {
|
||||||
|
let node_id = LiveId(i as u64).into();
|
||||||
|
popup_menu.draw_item(cx, node_id, item, self.icons[i].clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
popup_menu.end(cx, self.draw_bg.area());
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WechatDropDownRef {
|
||||||
|
pub fn item_clicked(&mut self, item_id: &[LiveId], actions: &Actions) -> bool {
|
||||||
|
if let Some(item) = actions.find_widget_action(self.widget_uid()) {
|
||||||
|
if let WechatDropDownAction::Select(_id, value) = item.cast() {
|
||||||
|
return LiveValue::Bool(true) == value.enum_eq(item_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
190
nimanyatta_v001/src/shared/header.rs
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
use crate::shared::dropdown_menu::*;
|
||||||
|
use crate::shared::stack_view_action::StackViewAction;
|
||||||
|
use makepad_widgets::widget::WidgetCache;
|
||||||
|
use makepad_widgets::*;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_draw::shader::std::*;
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
|
||||||
|
import crate::shared::styles::*;
|
||||||
|
import crate::shared::helpers::FillerX;
|
||||||
|
import crate::shared::dropdown_menu::DropDown;
|
||||||
|
|
||||||
|
SimpleHeaderContent = <View> {
|
||||||
|
width: Fill, height: Fit
|
||||||
|
flow: Right, align: {x: 0.5, y: 0.5}
|
||||||
|
|
||||||
|
<FillerX> {}
|
||||||
|
|
||||||
|
title_container = <View> {
|
||||||
|
width: Fill, height: Fit
|
||||||
|
align: {x: 0.5, y: 0.5}
|
||||||
|
|
||||||
|
title = <Label> {
|
||||||
|
width: Fit, height: Fit
|
||||||
|
draw_text: {
|
||||||
|
color: #000,
|
||||||
|
text_style: <TITLE_TEXT>{},
|
||||||
|
},
|
||||||
|
text: "微信"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleHeader = <View> {
|
||||||
|
width: Fill , height: Fit, margin: 0
|
||||||
|
padding: {bottom: 7., top: 50.}, align: {x: 0.5, y: 0.0}, spacing: 0.0, flow: Overlay
|
||||||
|
show_bg: true
|
||||||
|
draw_bg: {
|
||||||
|
color: #EDEDED
|
||||||
|
}
|
||||||
|
|
||||||
|
content = <SimpleHeaderContent> {}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeaderWithLeftActionButton = <SimpleHeader> {
|
||||||
|
content = {
|
||||||
|
flow: Overlay
|
||||||
|
|
||||||
|
button_container = <View> {
|
||||||
|
left_button = <Button> {
|
||||||
|
width: Fit, height: 68
|
||||||
|
icon_walk: {width: 20, height: 68}
|
||||||
|
draw_bg: {
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_icon: {
|
||||||
|
color: #000;
|
||||||
|
brightness: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
divider = <View> {
|
||||||
|
width: Fill, height: Fit
|
||||||
|
right_button = <Button> {
|
||||||
|
width: Fit, height: 68
|
||||||
|
icon_walk: {width: 20, height: 68}
|
||||||
|
draw_bg: {
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_icon: {
|
||||||
|
color: #000;
|
||||||
|
brightness: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeaderWithRightActionButton = <SimpleHeader> {
|
||||||
|
content = {
|
||||||
|
flow: Overlay
|
||||||
|
|
||||||
|
button_container = <View> {
|
||||||
|
spacer = <View> {
|
||||||
|
width: Fill, height: Fit
|
||||||
|
right_button = <Button> {
|
||||||
|
width: Fit, height: 68
|
||||||
|
icon_walk: {width: 20, height: 68}
|
||||||
|
draw_bg: {
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_icon: {
|
||||||
|
color: #000;
|
||||||
|
brightness: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HeaderDropDownMenu = {{HeaderDropDownMenu}} {
|
||||||
|
width: Fill, height: Fit, margin: 0
|
||||||
|
padding: {bottom: 7., top: 50.}, align: {x: 0.5, y: 0.0}, spacing: 0.0, flow: Overlay
|
||||||
|
show_bg: true
|
||||||
|
draw_bg: {
|
||||||
|
color: #EDEDED
|
||||||
|
}
|
||||||
|
|
||||||
|
content = <SimpleHeaderContent> {
|
||||||
|
width: Fill, height: Fit
|
||||||
|
flow: Right, align: {x: 0.5, y: 0.5}
|
||||||
|
|
||||||
|
button_container = <View> {
|
||||||
|
width: Fill, height: Fit
|
||||||
|
align: {x: 1.0, y: 0.5}, flow: Right, spacing: 5., padding: {right: 5.}
|
||||||
|
|
||||||
|
// TODO: this should be the searchbar, and we need consistent svgs
|
||||||
|
left_button = <Button> {
|
||||||
|
width: Fit, height: Fit
|
||||||
|
padding: 0.
|
||||||
|
icon_walk: {width: 20, height: Fit}
|
||||||
|
draw_bg: {
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size);
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_icon: {
|
||||||
|
svg_file: dep("crate://self/resources/icons/search.svg")
|
||||||
|
color: #000;
|
||||||
|
brightness: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
menu = <DropDown> {
|
||||||
|
height: Fit, width: Fit
|
||||||
|
draw_icon: {
|
||||||
|
svg_file: dep("crate://self/resources/icons/menu.svg")
|
||||||
|
color: #000;
|
||||||
|
brightness: 0.8;
|
||||||
|
}
|
||||||
|
labels: ["StepOneScreen", "New Chat", "Scan", "Money"]
|
||||||
|
values: [AddContact, NewChat, Scan, Money]
|
||||||
|
icons: [
|
||||||
|
dep("crate://self/resources/icons/add_contact.svg"),
|
||||||
|
dep("crate://self/resources/icons/chat.svg"),
|
||||||
|
dep("crate://self/resources/icons/scan.svg"),
|
||||||
|
dep("crate://self/resources/icons/money.svg")
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, LiveHook, Widget)]
|
||||||
|
pub struct HeaderDropDownMenu {
|
||||||
|
#[deref]
|
||||||
|
view: View,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for HeaderDropDownMenu {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
let uid = self.widget_uid();
|
||||||
|
let actions = cx.capture_actions(|cx| self.view.handle_event(cx, event, scope));
|
||||||
|
|
||||||
|
if self
|
||||||
|
.wechat_drop_down(id!(menu))
|
||||||
|
.item_clicked(id!(AddContact), &actions)
|
||||||
|
{
|
||||||
|
cx.widget_action(uid, &scope.path, StackViewAction::ShowAddContact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
self.view.draw_walk(cx, scope, walk)
|
||||||
|
}
|
||||||
|
}
|
27
nimanyatta_v001/src/shared/helpers.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
use makepad_widgets::*;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
|
||||||
|
Divider = <View> {
|
||||||
|
width: Fill, height: Fit
|
||||||
|
flow: Down
|
||||||
|
<RoundedView> {
|
||||||
|
width: Fill,
|
||||||
|
height: 1.,
|
||||||
|
draw_bg: {color: (#ddd)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LineH = <RoundedView> {
|
||||||
|
width: Fill,
|
||||||
|
height: 2,
|
||||||
|
margin: 0.0,
|
||||||
|
padding: 0.0, spacing: 0.0
|
||||||
|
draw_bg: {color: (COLOR_DIVIDER)}
|
||||||
|
}
|
||||||
|
|
||||||
|
FillerX = <View> { width: Fill, height: Fit }
|
||||||
|
FillerY = <View> { width: Fit, height: Fill }
|
||||||
|
}
|
|
@ -1,2 +1,11 @@
|
||||||
|
pub mod cho;
|
||||||
pub mod custom_button;
|
pub mod custom_button;
|
||||||
|
pub mod dropdown_menu;
|
||||||
|
pub mod header;
|
||||||
|
pub mod helpers;
|
||||||
|
pub mod popup_menu;
|
||||||
|
pub mod stack_navigation;
|
||||||
|
pub mod stack_view_action;
|
||||||
|
pub mod steps;
|
||||||
pub mod styles;
|
pub mod styles;
|
||||||
|
pub mod round_slider;
|
||||||
|
|
415
nimanyatta_v001/src/shared/popup_menu.rs
Normal file
|
@ -0,0 +1,415 @@
|
||||||
|
use makepad_widgets::makepad_derive_widget::*;
|
||||||
|
use makepad_widgets::makepad_draw::*;
|
||||||
|
use makepad_widgets::widget::*;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_draw::shader::std::*;
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
import crate::shared::styles::*;
|
||||||
|
|
||||||
|
MenuItem = {{MenuItem}} {
|
||||||
|
align: {y: 0.5},
|
||||||
|
padding: {left: 5., top: 10., bottom: 10., right: 5.},
|
||||||
|
spacing: 5.,
|
||||||
|
width: Fill,
|
||||||
|
height: Fit
|
||||||
|
|
||||||
|
draw_bg: {
|
||||||
|
instance color: #4
|
||||||
|
instance color_selected: #5
|
||||||
|
instance border_radius: 4.0
|
||||||
|
|
||||||
|
instance selected: 0.0
|
||||||
|
instance hover: 0.0
|
||||||
|
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
sdf.box(
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
self.rect_size.x,
|
||||||
|
self.rect_size.y,
|
||||||
|
self.border_radius
|
||||||
|
)
|
||||||
|
sdf.fill_keep(mix(self.color, self.color_selected, self.hover))
|
||||||
|
return sdf.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_name: {
|
||||||
|
text_style: <REGULAR_TEXT>{font_size: 9},
|
||||||
|
instance selected: 0.0
|
||||||
|
instance hover: 0.0
|
||||||
|
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
THEME_COLOR_TEXT_DEFAULT,
|
||||||
|
THEME_COLOR_TEXT_SELECTED,
|
||||||
|
self.selected
|
||||||
|
),
|
||||||
|
THEME_COLOR_TEXT_HOVER,
|
||||||
|
self.hover
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
icon_walk: {width: 15., height: Fit, margin: {bottom: 3.}}
|
||||||
|
draw_icon: {
|
||||||
|
color: #f2f2f2;
|
||||||
|
brightness: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
animator: {
|
||||||
|
hover = {
|
||||||
|
default: off
|
||||||
|
off = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {
|
||||||
|
draw_bg: {hover: 0.0}
|
||||||
|
draw_name: {hover: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
on = {
|
||||||
|
cursor: Hand
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {
|
||||||
|
draw_bg: {hover: 1.0}
|
||||||
|
draw_name: {hover: 1.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
select = {
|
||||||
|
default: off
|
||||||
|
off = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {
|
||||||
|
draw_bg: {selected: 0.0,}
|
||||||
|
draw_name: {selected: 0.0,}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
on = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {
|
||||||
|
draw_bg: {selected: 1.0,}
|
||||||
|
draw_name: {selected: 1.0,}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
indent_width: 10.0
|
||||||
|
}
|
||||||
|
|
||||||
|
PopupMenu = {{PopupMenu}} {
|
||||||
|
menu_item: <MenuItem> {}
|
||||||
|
flow: Down,
|
||||||
|
padding: 5.,
|
||||||
|
width: 140.,
|
||||||
|
height: Fit,
|
||||||
|
|
||||||
|
icon_walk: {width: 20., height: Fit}
|
||||||
|
draw_icon:{
|
||||||
|
instance hover: 0.0
|
||||||
|
instance pressed: 0.0
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
#9,
|
||||||
|
#c,
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
#9,
|
||||||
|
self.pressed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_bg: {
|
||||||
|
instance color: #4
|
||||||
|
instance border_width: 0.0,
|
||||||
|
instance border_color: #4,
|
||||||
|
instance border_radius: 4.0
|
||||||
|
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return self.color
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_border_color(self) -> vec4 {
|
||||||
|
return self.border_color
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
// sdf.blur = 18.0;
|
||||||
|
sdf.box(
|
||||||
|
self.border_width,
|
||||||
|
self.border_width,
|
||||||
|
self.rect_size.x - (self.border_width * 2.0),
|
||||||
|
self.rect_size.y - (self.border_width * 2.0),
|
||||||
|
self.border_radius
|
||||||
|
)
|
||||||
|
sdf.fill_keep(self.get_color())
|
||||||
|
return sdf.result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, LiveRegister, WidgetWrap)]
|
||||||
|
pub struct PopupMenu {
|
||||||
|
#[live]
|
||||||
|
draw_list: DrawList2d,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
menu_item: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_bg: DrawQuad,
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_icon: DrawIcon,
|
||||||
|
#[live]
|
||||||
|
icon_walk: Walk,
|
||||||
|
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
labels: Vec<String>,
|
||||||
|
#[live]
|
||||||
|
values: Vec<LiveValue>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
items: Vec<String>,
|
||||||
|
#[rust]
|
||||||
|
menu_items: ComponentMap<MenuItemId, MenuItem>,
|
||||||
|
#[rust]
|
||||||
|
init_select_item: Option<MenuItemId>,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
first_tap: bool,
|
||||||
|
#[rust]
|
||||||
|
count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for PopupMenu {
|
||||||
|
fn after_apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) {
|
||||||
|
if let Some(index) = nodes.child_by_name(index, live_id!(list_node).as_field()) {
|
||||||
|
for (_, node) in self.menu_items.iter_mut() {
|
||||||
|
node.apply(cx, apply, index, nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.draw_list.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for PopupMenu {
|
||||||
|
fn handle_event(&mut self, _cx: &mut Cx, _event: &Event, _scope: &mut Scope) {}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
self.draw_bg.begin(cx, walk, self.layout);
|
||||||
|
self.draw_icon.draw_walk(cx, self.icon_walk);
|
||||||
|
self.draw_bg.end(cx);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PopupMenu {
|
||||||
|
pub fn menu_contains_pos(&self, cx: &mut Cx, pos: DVec2) -> bool {
|
||||||
|
self.draw_bg.area().clipped_rect(cx).contains(pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn begin(&mut self, cx: &mut Cx2d) {
|
||||||
|
self.draw_list.begin_overlay_reuse(cx);
|
||||||
|
|
||||||
|
cx.begin_pass_sized_turtle(Layout::flow_down());
|
||||||
|
|
||||||
|
self.draw_bg.begin(cx, self.walk, self.layout);
|
||||||
|
self.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end(&mut self, cx: &mut Cx2d, shift_area: Area) {
|
||||||
|
self.draw_bg.end(cx);
|
||||||
|
let area = self.draw_bg.area().rect(cx);
|
||||||
|
let shift = DVec2 {
|
||||||
|
x: -area.size.x + (shift_area.rect(cx).size.x * 0.7),
|
||||||
|
y: 30.,
|
||||||
|
};
|
||||||
|
|
||||||
|
cx.end_pass_sized_turtle_with_shift(shift_area, shift);
|
||||||
|
self.draw_list.end(cx);
|
||||||
|
|
||||||
|
self.menu_items.retain_visible();
|
||||||
|
if let Some(init_select_item) = self.init_select_item.take() {
|
||||||
|
self.select_item_state(cx, init_select_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_item(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx2d,
|
||||||
|
item_id: MenuItemId,
|
||||||
|
label: &str,
|
||||||
|
icon: LiveDependency,
|
||||||
|
) {
|
||||||
|
self.count += 1;
|
||||||
|
|
||||||
|
let menu_item = self.menu_item;
|
||||||
|
let menu_item = self
|
||||||
|
.menu_items
|
||||||
|
.get_or_insert(cx, item_id, |cx| MenuItem::new_from_ptr(cx, menu_item));
|
||||||
|
menu_item.draw_item(cx, label, icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_select_item(&mut self, which_id: MenuItemId) {
|
||||||
|
self.init_select_item = Some(which_id);
|
||||||
|
self.first_tap = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_item_state(&mut self, cx: &mut Cx, which_id: MenuItemId) {
|
||||||
|
for (id, item) in &mut *self.menu_items {
|
||||||
|
if *id == which_id {
|
||||||
|
item.animator_cut(cx, id!(select.on));
|
||||||
|
item.animator_cut(cx, id!(hover.on));
|
||||||
|
} else {
|
||||||
|
item.animator_cut(cx, id!(select.off));
|
||||||
|
item.animator_cut(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_event_with(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx,
|
||||||
|
event: &Event,
|
||||||
|
sweep_area: Area,
|
||||||
|
dispatch_action: &mut dyn FnMut(&mut Cx, PopupMenuAction),
|
||||||
|
) {
|
||||||
|
let mut actions = Vec::new();
|
||||||
|
for (item_id, node) in self.menu_items.iter_mut() {
|
||||||
|
node.handle_event_with(cx, event, sweep_area, &mut |_, e| {
|
||||||
|
actions.push((*item_id, e))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (node_id, action) in actions {
|
||||||
|
match action {
|
||||||
|
MenuItemAction::WasSweeped => {
|
||||||
|
self.select_item_state(cx, node_id);
|
||||||
|
dispatch_action(cx, PopupMenuAction::WasSweeped(node_id));
|
||||||
|
}
|
||||||
|
MenuItemAction::WasSelected => {
|
||||||
|
self.select_item_state(cx, node_id);
|
||||||
|
dispatch_action(cx, PopupMenuAction::WasSelected(node_id));
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, LiveHook, LiveRegister, WidgetWrap)]
|
||||||
|
pub struct MenuItem {
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_bg: DrawQuad,
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_name: DrawText,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_icon: DrawIcon,
|
||||||
|
#[live]
|
||||||
|
icon_walk: Walk,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
indent_width: f32,
|
||||||
|
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
#[live]
|
||||||
|
opened: f32,
|
||||||
|
#[live]
|
||||||
|
hover: f32,
|
||||||
|
#[live]
|
||||||
|
selected: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Debug)]
|
||||||
|
pub enum MenuItemAction {
|
||||||
|
WasSweeped,
|
||||||
|
WasSelected,
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, DefaultNone, Debug)]
|
||||||
|
pub enum PopupMenuAction {
|
||||||
|
WasSweeped(MenuItemId),
|
||||||
|
WasSelected(MenuItemId),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Default, Eq, Hash, Copy, PartialEq, FromLiveId)]
|
||||||
|
pub struct MenuItemId(pub LiveId);
|
||||||
|
|
||||||
|
impl MenuItem {
|
||||||
|
pub fn draw_item(&mut self, cx: &mut Cx2d, label: &str, icon: LiveDependency) {
|
||||||
|
self.draw_bg.begin(cx, self.walk, self.layout);
|
||||||
|
self.draw_icon.svg_file = icon;
|
||||||
|
self.draw_icon.draw_walk(cx, self.icon_walk);
|
||||||
|
self.draw_name
|
||||||
|
.draw_walk(cx, Walk::fit(), Align { x: 0., y: 0.5 }, label);
|
||||||
|
self.draw_bg.end(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_event_with(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx,
|
||||||
|
event: &Event,
|
||||||
|
sweep_area: Area,
|
||||||
|
dispatch_action: &mut dyn FnMut(&mut Cx, MenuItemAction),
|
||||||
|
) {
|
||||||
|
if self.animator_handle_event(cx, event).must_redraw() {
|
||||||
|
self.draw_bg.area().redraw(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
match event.hits_with_options(
|
||||||
|
cx,
|
||||||
|
self.draw_bg.area(),
|
||||||
|
HitOptions::new().with_sweep_area(sweep_area),
|
||||||
|
) {
|
||||||
|
Hit::FingerHoverIn(_) => {
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
}
|
||||||
|
Hit::FingerHoverOut(_) => {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
Hit::FingerDown(_) => {
|
||||||
|
dispatch_action(cx, MenuItemAction::WasSweeped);
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
self.animator_play(cx, id!(select.on));
|
||||||
|
}
|
||||||
|
Hit::FingerUp(se) => {
|
||||||
|
if !se.is_sweep {
|
||||||
|
dispatch_action(cx, MenuItemAction::WasSelected);
|
||||||
|
} else {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
self.animator_play(cx, id!(select.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
99
nimanyatta_v001/src/shared/round_slider.rs
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
use makepad_widgets::*;
|
||||||
|
// const CHOICE_MAX_OFFSET: f64 = 400.0;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_draw::shader::std::*;
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
import crate::shared::styles::*;
|
||||||
|
import crate::shared::steps::StepNav;
|
||||||
|
import crate::shared::custom_button::CustomButton;
|
||||||
|
RoundSlider = <Slider> {
|
||||||
|
// height: 36
|
||||||
|
height: 300
|
||||||
|
text: "CutOff1"
|
||||||
|
draw_text: {text_style: <H2_TEXT_BOLD> {}, color: (COLOR_UP_5)}
|
||||||
|
text_input: {
|
||||||
|
cursor_margin_bottom: (SSPACING_1),
|
||||||
|
cursor_margin_top: (SSPACING_1),
|
||||||
|
select_pad_edges: (SSPACING_1),
|
||||||
|
cursor_size: (SSPACING_1),
|
||||||
|
empty_message: "0",
|
||||||
|
numeric_only: true,
|
||||||
|
draw_bg: {
|
||||||
|
color: (COLOR_DOWN_0)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
draw_slider: {
|
||||||
|
instance hover: float
|
||||||
|
instance focus: float
|
||||||
|
instance drag: float
|
||||||
|
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let slider_height = 10;
|
||||||
|
let offset = 150;
|
||||||
|
let nub_size = mix(3, 4, self.hover);
|
||||||
|
let nubbg_size = 18
|
||||||
|
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
|
||||||
|
let slider_bg_color = mix(#38, #30, self.focus);
|
||||||
|
let slider_color = mix(mix(#x086975, #x086975, self.hover), #x086975, self.focus);
|
||||||
|
let nub_color = mix(mix(#8, #f, self.hover), mix(#c, #f, self.drag), self.focus);
|
||||||
|
let nubbg_color = mix(#eee0, #8, self.drag);
|
||||||
|
|
||||||
|
sdf.rect(0, self.rect_size.y - slider_height-offset, self.rect_size.x, slider_height)
|
||||||
|
sdf.fill(slider_bg_color);
|
||||||
|
|
||||||
|
sdf.rect(0, self.rect_size.y - slider_height-offset, self.slide_pos * (self.rect_size.x - nub_size) + nub_size, slider_height)
|
||||||
|
sdf.fill(slider_color);
|
||||||
|
|
||||||
|
let nubbg_x = self.slide_pos * (self.rect_size.x - nub_size) - nubbg_size * 0.5 + 0.5 * nub_size;
|
||||||
|
sdf.rect(nubbg_x, self.rect_size.y - slider_height-offset, nubbg_size, slider_height)
|
||||||
|
sdf.fill(nubbg_color);
|
||||||
|
|
||||||
|
// the nub
|
||||||
|
let nub_x = self.slide_pos * (self.rect_size.x - nub_size);
|
||||||
|
sdf.circle(nub_x, self.rect_size.y - slider_height-(offset-5), slider_height);
|
||||||
|
// sdf.rect(nub_x, self.rect_size.y - slider_height-100, nub_size, slider_height)
|
||||||
|
sdf.fill_keep(mix(mix(#xF6FCFD, #xF6FCFD, self.hover), #xF6FCFD, self.pos.y)); // Nub background gradient
|
||||||
|
sdf.stroke(
|
||||||
|
mix(
|
||||||
|
mix(#x00bbd3, #x00bbd3, self.hover),
|
||||||
|
#x00bbd3,
|
||||||
|
pow(self.pos.y, 1.5)
|
||||||
|
),
|
||||||
|
1.
|
||||||
|
); // Nub outline gradient
|
||||||
|
// sdf.fill(nub_color);
|
||||||
|
|
||||||
|
// // let nub_x = self.slide_pos * (self.rect_size.x - nub_size - in_side * 2 - 9);
|
||||||
|
// let cnub_x = self.slide_pos * (self.rect_size.x - nub_size - cin_side * 2 - 9);
|
||||||
|
// let diameter = 7.0
|
||||||
|
// // sdf.move_to(mix(in_side + 3.5, self.rect_size.x * 0.5, self.bipolar), top + in_top);
|
||||||
|
// sdf.move_to(mix(cin_side + 3.5, self.rect_size.x * 0.5, self.bipolar), top + cin_top);
|
||||||
|
|
||||||
|
// sdf.line_to(nub_x + cin_side + nub_size * 0.5, top + cin_top);
|
||||||
|
// sdf.stroke_keep(mix((COLOR_UP_0), self.line_color, self.drag), 1.5)
|
||||||
|
// sdf.stroke(
|
||||||
|
// mix(mix(self.line_color * 0.85, self.line_color, self.hover), #xFFFFFF80, self.drag),
|
||||||
|
// 1
|
||||||
|
// )
|
||||||
|
|
||||||
|
// let nub_x = self.slide_pos * (self.rect_size.x - nub_size - in_side * 2 - 3) - 3;
|
||||||
|
// sdf.circle(nub_x + in_side, top + 7.0, diameter);
|
||||||
|
// sdf.fill_keep(mix(mix(#xF6FCFD, #xF6FCFD, self.hover), #xF6FCFD, self.pos.y)); // Nub background gradient
|
||||||
|
// sdf.stroke(
|
||||||
|
// mix(
|
||||||
|
// mix(#x00bbd3, #x00bbd3, self.hover),
|
||||||
|
// #x00bbd3,
|
||||||
|
// pow(self.pos.y, 1.5)
|
||||||
|
// ),
|
||||||
|
// 1.
|
||||||
|
// ); // Nub outline gradient
|
||||||
|
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
258
nimanyatta_v001/src/shared/stack_navigation.rs
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
use makepad_widgets::widget::WidgetCache;
|
||||||
|
use makepad_widgets::*;
|
||||||
|
use crate::shared::stack_view_action::StackViewAction;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
import crate::shared::header::HeaderWithLeftActionButton;
|
||||||
|
|
||||||
|
FillerY = <View> {width: Fill}
|
||||||
|
|
||||||
|
FillerX = <View> {height: Fill}
|
||||||
|
|
||||||
|
Header = <HeaderWithLeftActionButton> {
|
||||||
|
content = {
|
||||||
|
title_container = {
|
||||||
|
title = {
|
||||||
|
text: "My Stack View"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button_container = {
|
||||||
|
left_button = {
|
||||||
|
width: Fit
|
||||||
|
icon_walk: {width: 10}
|
||||||
|
draw_icon: {
|
||||||
|
svg_file: dep("crate://self/resources/icons/arrow_back.svg")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StackNavigationView = {{StackNavigationView}} {
|
||||||
|
visible: false
|
||||||
|
width: Fill, height: Fill
|
||||||
|
flow: Down
|
||||||
|
show_bg: true
|
||||||
|
draw_bg: {
|
||||||
|
color: #fff
|
||||||
|
}
|
||||||
|
debug: A
|
||||||
|
header = <Header> {}
|
||||||
|
<FillerY> {}
|
||||||
|
|
||||||
|
// TBD Adjust this based on actual screen size
|
||||||
|
// offset: 400.0
|
||||||
|
offset: 2.0
|
||||||
|
|
||||||
|
animator: {
|
||||||
|
slide = {
|
||||||
|
default: hide,
|
||||||
|
hide = {
|
||||||
|
ease: ExpDecay {d1: 0.80, d2: 0.97}
|
||||||
|
from: {all: Forward {duration: 0.3}}
|
||||||
|
// Bug: Constants are not working as part of an live state value
|
||||||
|
// apply: {offset: 400.0}
|
||||||
|
apply: {offset: 1.0}
|
||||||
|
}
|
||||||
|
|
||||||
|
show = {
|
||||||
|
ease: ExpDecay {d1: 0.82, d2: 0.95}
|
||||||
|
from: {all: Forward {duration: 0.3}}
|
||||||
|
apply: {offset: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StackNavigation = {{StackNavigation}} {
|
||||||
|
width: Fill, height: Fill
|
||||||
|
flow: Overlay
|
||||||
|
|
||||||
|
root_view = <View> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, LiveHook, Widget)]
|
||||||
|
pub struct StackNavigationView {
|
||||||
|
#[deref]
|
||||||
|
view:View,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
offset: f64,
|
||||||
|
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for StackNavigationView {
|
||||||
|
fn handle_event(&mut self, cx:&mut Cx, event:&Event, scope:&mut Scope) {
|
||||||
|
if self.animator_handle_event(cx, event).is_animating() {
|
||||||
|
self.view.redraw(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
let actions = cx.capture_actions(|cx| self.view.handle_event(cx, event, scope));
|
||||||
|
if self.button(id!(left_button)).clicked(&actions) {
|
||||||
|
self.animator_play(cx, id!(slide.hide));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.animator.animator_in_state(cx, id!(slide.hide))
|
||||||
|
&& !self.animator.is_track_animating(cx, id!(slide))
|
||||||
|
{
|
||||||
|
self.apply_over(cx, live! {visible: false});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx:&mut Cx2d, scope:&mut Scope, walk:Walk) -> DrawStep{
|
||||||
|
self.view.draw_walk(
|
||||||
|
cx,
|
||||||
|
scope,
|
||||||
|
walk.with_abs_pos(DVec2 {
|
||||||
|
x: self.offset,
|
||||||
|
y: 0.,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StackNavigationViewRef {
|
||||||
|
pub fn show(&mut self, cx: &mut Cx) {
|
||||||
|
if let Some(mut inner) = self.borrow_mut() {
|
||||||
|
inner.apply_over(cx, live! {visible: true});
|
||||||
|
inner.animator_play(cx, id!(slide.show));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_showing(&self, cx: &mut Cx) -> bool {
|
||||||
|
if let Some(inner) = self.borrow() {
|
||||||
|
inner.animator.animator_in_state(cx, id!(slide.show))
|
||||||
|
|| inner.animator.is_track_animating(cx, id!(slide))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_animating(&self, cx: &mut Cx) -> bool {
|
||||||
|
if let Some(inner) = self.borrow() {
|
||||||
|
inner.animator.is_track_animating(cx, id!(slide))
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
enum ActiveStackView {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
Active(LiveId),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, LiveRegisterWidget, WidgetRef)]
|
||||||
|
pub struct StackNavigation {
|
||||||
|
#[deref]
|
||||||
|
view: View,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
active_stack_view: ActiveStackView,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for StackNavigation {
|
||||||
|
fn after_new_from_doc(&mut self, _cx: &mut Cx) {
|
||||||
|
self.active_stack_view = ActiveStackView::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for StackNavigation {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
for widget_ref in self.get_active_views(cx).iter() {
|
||||||
|
widget_ref.handle_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
for widget_ref in self.get_active_views(cx.cx).iter() {
|
||||||
|
widget_ref.draw_walk(cx, scope, walk) ?;
|
||||||
|
}
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetNode for StackNavigation {
|
||||||
|
fn walk(&mut self, cx:&mut Cx) -> Walk{
|
||||||
|
self.view.walk(cx)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn redraw(&mut self, cx: &mut Cx) {
|
||||||
|
for widget_ref in self.get_active_views(cx).iter() {
|
||||||
|
widget_ref.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_widgets(&mut self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) {
|
||||||
|
self.view.find_widgets(path, cached, results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl StackNavigation {
|
||||||
|
pub fn show_stack_view_by_id(&mut self, stack_view_id: LiveId, cx: &mut Cx) {
|
||||||
|
if let ActiveStackView::None = self.active_stack_view {
|
||||||
|
let mut stack_view_ref = self.stack_navigation_view(&[stack_view_id]);
|
||||||
|
stack_view_ref.show(cx);
|
||||||
|
self.active_stack_view = ActiveStackView::Active(stack_view_id);
|
||||||
|
self.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_active_views(&mut self, cx: &mut Cx) -> Vec<WidgetRef> {
|
||||||
|
match self.active_stack_view {
|
||||||
|
ActiveStackView::None => {
|
||||||
|
vec![self.view.widget(id!(root_view))]
|
||||||
|
},
|
||||||
|
ActiveStackView::Active(stack_view_id) => {
|
||||||
|
let stack_view_ref = self.stack_navigation_view(&[stack_view_id]);
|
||||||
|
let mut views = vec![];
|
||||||
|
|
||||||
|
if stack_view_ref.is_showing(cx) {
|
||||||
|
if stack_view_ref.is_animating(cx) {
|
||||||
|
views.push(self.view.widget(id!(root_view)));
|
||||||
|
}
|
||||||
|
views.push(stack_view_ref.0.clone());
|
||||||
|
views
|
||||||
|
} else {
|
||||||
|
self.active_stack_view = ActiveStackView::None;
|
||||||
|
vec![self.view.widget(id!(root_view))]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StackNavigationRef {
|
||||||
|
pub fn show_stack_view_by_id(&mut self, stack_view_id: LiveId, cx: &mut Cx) {
|
||||||
|
if let Some(mut inner) = self.borrow_mut() {
|
||||||
|
inner.show_stack_view_by_id(stack_view_id, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_stack_view_actions(&mut self, cx: &mut Cx, actions: &Actions, destinations: &HashMap<StackViewAction, LiveId>) {
|
||||||
|
for action in actions {
|
||||||
|
let stack_view_action = action.as_widget_action().cast();
|
||||||
|
if let Some(stack_view_id) = destinations.get(&stack_view_action) {
|
||||||
|
self.show_stack_view_by_id(*stack_view_id, cx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_title(&self, stack_view_id: LiveId, title: &str) {
|
||||||
|
if let Some(mut inner) = self.borrow_mut() {
|
||||||
|
let stack_view_ref = inner.stack_navigation_view(&[stack_view_id]);
|
||||||
|
stack_view_ref.label(id!(title)).set_text(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
nimanyatta_v001/src/shared/stack_view_action.rs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
use makepad_widgets::*;
|
||||||
|
|
||||||
|
#[derive(Clone, DefaultNone, Eq, Hash, PartialEq, Debug)]
|
||||||
|
pub enum StackViewAction {
|
||||||
|
None,
|
||||||
|
ShowAddContact,
|
||||||
|
ShowMoments,
|
||||||
|
ShowCounterScreen,
|
||||||
|
ShowDefaultChoiceScreen,
|
||||||
|
ShowMyProfile,
|
||||||
|
ShowChat,
|
||||||
|
}
|
846
nimanyatta_v001/src/shared/steps.rs
Normal file
|
@ -0,0 +1,846 @@
|
||||||
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
use makepad_widgets::*;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_draw::shader::std::*;
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
|
||||||
|
DrawStepsNav = {{DrawStepsNav}} {}
|
||||||
|
StepsNavBase = {{StepsNav}} {}
|
||||||
|
StepNav = <StepsNavBase> {
|
||||||
|
|
||||||
|
width: Fit,
|
||||||
|
height: Fit
|
||||||
|
|
||||||
|
label_walk: {
|
||||||
|
margin: {left: 20.0, top: 8, bottom: 8, right: 10}
|
||||||
|
width: Fit,
|
||||||
|
height: Fit,
|
||||||
|
}
|
||||||
|
|
||||||
|
label_align: {
|
||||||
|
y: 0.0
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_check: {
|
||||||
|
uniform size: 7.0;
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
let sdf = Sdf2d::viewport(self.pos * self.rect_size)
|
||||||
|
match self.check_type {
|
||||||
|
CheckType::Check => {
|
||||||
|
let left = 3;
|
||||||
|
let sz = self.size;
|
||||||
|
let c = vec2(left + sz, self.rect_size.y * 0.5);
|
||||||
|
sdf.box(left, c.y - sz, sz * 2.0, sz * 2.0, 3.0); // rounding = 3rd value
|
||||||
|
sdf.fill_keep(mix(mix(#x00000077, #x00000044, pow(self.pos.y, 1.)), mix(#x000000AA, #x00000066, pow(self.pos.y, 1.0)), self.hover))
|
||||||
|
sdf.stroke(#x888, 1.0) // outline
|
||||||
|
let szs = sz * 0.5;
|
||||||
|
let dx = 1.0;
|
||||||
|
sdf.move_to(left + 4.0, c.y);
|
||||||
|
sdf.line_to(c.x, c.y + szs);
|
||||||
|
sdf.line_to(c.x + szs, c.y - szs);
|
||||||
|
sdf.stroke(mix(#fff0, #f, self.selected), 1.25);
|
||||||
|
}
|
||||||
|
CheckType::Radio => {
|
||||||
|
let sz = self.size;
|
||||||
|
let left = sz + 1.;
|
||||||
|
let c = vec2(left + sz, self.rect_size.y * 0.5);
|
||||||
|
sdf.circle(left, c.y, sz);
|
||||||
|
sdf.fill(#2);
|
||||||
|
let isz = sz * 0.5;
|
||||||
|
sdf.circle(left, c.y, isz);
|
||||||
|
sdf.fill(mix(#fff0, #f, self.selected));
|
||||||
|
}
|
||||||
|
CheckType::Toggle => {
|
||||||
|
let sz = self.size;
|
||||||
|
let left = sz + 1.;
|
||||||
|
let c = vec2(left + sz, self.rect_size.y * 0.5);
|
||||||
|
sdf.box(left, c.y - sz, sz * 3.0, sz * 2.0, 0.5 * sz);
|
||||||
|
sdf.fill(#2);
|
||||||
|
let isz = sz * 0.5;
|
||||||
|
sdf.circle(left + sz + self.selected * sz, c.y, isz);
|
||||||
|
sdf.circle(left + sz + self.selected * sz, c.y, 0.5 * isz);
|
||||||
|
sdf.subtract();
|
||||||
|
sdf.circle(left + sz + self.selected * sz, c.y, isz);
|
||||||
|
sdf.blend(self.selected)
|
||||||
|
sdf.fill(#f);
|
||||||
|
}
|
||||||
|
CheckType::None => {
|
||||||
|
return #0000
|
||||||
|
}
|
||||||
|
CheckType::Bar => {
|
||||||
|
let sz = self.size;
|
||||||
|
let left = sz + 1.;
|
||||||
|
let up = sz + 3.5;
|
||||||
|
let c = self.rect_size * vec2(0.5, 0.5);
|
||||||
|
sdf.box(
|
||||||
|
left,
|
||||||
|
c.y - up,
|
||||||
|
12. * sz + 5,
|
||||||
|
1. * sz,
|
||||||
|
1.9
|
||||||
|
);
|
||||||
|
|
||||||
|
sdf.fill(#232323);
|
||||||
|
sdf.stroke(#000, 0.5 + 0.5 * self.dpi_dilate);
|
||||||
|
|
||||||
|
let isz = sz * 0.5;
|
||||||
|
let ileft = isz + 4.5;
|
||||||
|
let iup = sz + 3.5;
|
||||||
|
sdf.box(
|
||||||
|
ileft,
|
||||||
|
c.y - iup,
|
||||||
|
12. * sz + 5,
|
||||||
|
1. * sz,
|
||||||
|
1.9
|
||||||
|
);
|
||||||
|
sdf.fill(mix(#fff0, #016def, self.selected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sdf.result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
draw_text: {
|
||||||
|
color: #9,
|
||||||
|
instance focus: 0.0
|
||||||
|
instance selected: 0.0
|
||||||
|
instance hover: 0.0
|
||||||
|
text_style: {
|
||||||
|
font: {
|
||||||
|
//path: d"resources/IBMPlexSans-SemiBold.ttf"
|
||||||
|
}
|
||||||
|
font_size: 11.0
|
||||||
|
}
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
#fff6,
|
||||||
|
#fff6,
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
#fff6,
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_icon: {
|
||||||
|
instance focus: 0.0
|
||||||
|
instance hover: 0.0
|
||||||
|
instance selected: 0.0
|
||||||
|
fn get_color(self) -> vec4 {
|
||||||
|
return mix(
|
||||||
|
mix(
|
||||||
|
#9,
|
||||||
|
#c,
|
||||||
|
self.hover
|
||||||
|
),
|
||||||
|
#f,
|
||||||
|
self.selected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
animator: {
|
||||||
|
hover = {
|
||||||
|
default: off
|
||||||
|
off = {
|
||||||
|
from: {all: Forward {duration: 0.15}}
|
||||||
|
apply: {
|
||||||
|
draw_check: {hover: 0.0}
|
||||||
|
draw_text: {hover: 0.0}
|
||||||
|
draw_icon: {hover: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
on = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {
|
||||||
|
draw_check: {hover: 1.0}
|
||||||
|
draw_text: {hover: 1.0}
|
||||||
|
draw_icon: {hover: 1.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
focus = {
|
||||||
|
default: off
|
||||||
|
off = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {
|
||||||
|
draw_check: {focus: 0.0}
|
||||||
|
draw_text: {focus: 0.0}
|
||||||
|
draw_icon: {focus: 0.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
on = {
|
||||||
|
from: {all: Snap}
|
||||||
|
apply: {
|
||||||
|
draw_check: {focus: 1.0}
|
||||||
|
draw_text: {focus: 1.0}
|
||||||
|
draw_icon: {focus: 1.0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selected = {
|
||||||
|
default: off
|
||||||
|
off = {
|
||||||
|
from: {all: Forward {duration: 0.1}}
|
||||||
|
apply: {
|
||||||
|
draw_check: {selected: 0.0},
|
||||||
|
draw_text: {selected: 0.0},
|
||||||
|
draw_icon: {selected: 0.0},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
on = {
|
||||||
|
from: {all: Forward {duration: 0.0}}
|
||||||
|
apply: {
|
||||||
|
draw_check: {selected: 1.0}
|
||||||
|
draw_text: {selected: 1.0}
|
||||||
|
draw_icon: {selected: 1.0},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Choices = {{Choices}} {
|
||||||
|
<View> {
|
||||||
|
flow: Down,
|
||||||
|
align: {x: 0.5, y: 0.3}
|
||||||
|
debug: A
|
||||||
|
choice_item: <StepNav> {
|
||||||
|
width: 100, height: 20,
|
||||||
|
margin: 0, padding: 0
|
||||||
|
flow: Right,
|
||||||
|
align: {x: 0.5, y: 0.5},
|
||||||
|
// show_bg: true
|
||||||
|
draw_check: {
|
||||||
|
check_type: Bar,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
width: 100, height: 100,
|
||||||
|
// flow: Down,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ChoicesComponent = {{ChoicesComponent}} {
|
||||||
|
choices = <Choices>{}
|
||||||
|
}
|
||||||
|
// Choices = <StepNav> {
|
||||||
|
// width: 100, height: 20,
|
||||||
|
// margin: 0, padding: 0
|
||||||
|
// flow: Right,
|
||||||
|
// align: {x: 0.5, y: 0.5},
|
||||||
|
// // show_bg: true
|
||||||
|
// draw_check: {
|
||||||
|
// check_type: Bar,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct ChoicesComponent {
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_bg: DrawQuad,
|
||||||
|
#[live]
|
||||||
|
draw_icon: DrawIcon,
|
||||||
|
#[live]
|
||||||
|
icon_walk: Walk,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
bind: String,
|
||||||
|
#[live]
|
||||||
|
bind_enum: String,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
choices: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
labels: Vec<String>,
|
||||||
|
#[live]
|
||||||
|
values: Vec<LiveValue>,
|
||||||
|
#[live]
|
||||||
|
icons: Vec<LiveDependency>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
popup_shift: DVec2,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
is_open: bool,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
selected_item: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for ChoicesComponent {
|
||||||
|
fn after_apply_from(&mut self, cx: &mut Cx, apply: &mut Apply) {
|
||||||
|
if self.choices.is_none() || !apply.from.is_from_doc() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let global = cx.global::<ChoicesGlobal>().clone();
|
||||||
|
let mut map = global.map.borrow_mut();
|
||||||
|
|
||||||
|
// when live styling clean up old style references
|
||||||
|
map.retain(|k, _| cx.live_registry.borrow().generation_valid(*k));
|
||||||
|
|
||||||
|
let list_box = self.choices.unwrap();
|
||||||
|
map.get_or_insert(cx, list_box, |cx| Choices::new_from_ptr(cx, Some(list_box)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Clone, DefaultNone, Debug)]
|
||||||
|
pub enum ChoicesComponentAction {
|
||||||
|
Select(usize, LiveValue),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
impl Widget for ChoicesComponent {
|
||||||
|
fn widget_to_data(
|
||||||
|
&self,
|
||||||
|
_cx: &mut Cx,
|
||||||
|
actions: &Actions,
|
||||||
|
nodes: &mut LiveNodeVec,
|
||||||
|
path: &[LiveId],
|
||||||
|
) -> bool {
|
||||||
|
match actions.find_widget_action(self.widget_uid()).cast() {
|
||||||
|
ChoicesComponentAction::Select(_, value) => {
|
||||||
|
nodes.write_field_value(path, value.clone());
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_to_widget(&mut self, cx: &mut Cx, nodes: &[LiveNode], path: &[LiveId]) {
|
||||||
|
if let Some(value) = nodes.read_field_value(path) {
|
||||||
|
if let Some(index) = self.values.iter().position(|v| v == value) {
|
||||||
|
if self.selected_item != index {
|
||||||
|
self.selected_item = index;
|
||||||
|
self.redraw(cx);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// error!("Value not in values list {:?}", value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
self.animator_handle_event(cx, event);
|
||||||
|
let uid = self.widget_uid();
|
||||||
|
|
||||||
|
if self.choices.is_some() {
|
||||||
|
let global = cx.global::<ChoicesGlobal>().clone();
|
||||||
|
let mut map = global.map.borrow_mut();
|
||||||
|
let menu = map.get_mut(&self.choices.unwrap()).unwrap();
|
||||||
|
let mut close = false;
|
||||||
|
menu.handle_event_with(cx, event, self.draw_bg.area(), &mut |cx, action| {
|
||||||
|
if let ChoicesAction::WasSelected(node_id) = action {
|
||||||
|
self.selected_item = node_id.0 .0 as usize;
|
||||||
|
cx.widget_action(
|
||||||
|
uid,
|
||||||
|
&scope.path,
|
||||||
|
ChoicesComponentAction::Select(
|
||||||
|
self.selected_item,
|
||||||
|
self.values
|
||||||
|
.get(self.selected_item)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(LiveValue::None),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
self.draw_bg.redraw(cx);
|
||||||
|
close = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// if close {
|
||||||
|
// self.set_closed(cx);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// check if we touch outside of the popup menu
|
||||||
|
if let Event::MouseDown(e) = event {
|
||||||
|
if !menu.menu_contains_pos(cx, e.abs) {
|
||||||
|
// self.set_closed(cx);
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: close on clicking outside of the popup menu
|
||||||
|
match event.hits_with_sweep_area(cx, self.draw_bg.area(), self.draw_bg.area()) {
|
||||||
|
Hit::KeyFocusLost(_) => {
|
||||||
|
// self.set_closed(cx);
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
self.draw_bg.redraw(cx);
|
||||||
|
}
|
||||||
|
Hit::KeyDown(ke) => match ke.key_code {
|
||||||
|
KeyCode::ArrowUp => {
|
||||||
|
if self.selected_item > 0 {
|
||||||
|
self.selected_item -= 1;
|
||||||
|
cx.widget_action(
|
||||||
|
uid,
|
||||||
|
&scope.path,
|
||||||
|
ChoicesComponentAction::Select(
|
||||||
|
self.selected_item,
|
||||||
|
self.values
|
||||||
|
.get(self.selected_item)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(LiveValue::None),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// self.set_closed(cx);
|
||||||
|
self.draw_bg.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyCode::ArrowDown => {
|
||||||
|
if !self.values.is_empty() && self.selected_item < self.values.len() - 1 {
|
||||||
|
self.selected_item += 1;
|
||||||
|
cx.widget_action(
|
||||||
|
uid,
|
||||||
|
&scope.path,
|
||||||
|
ChoicesComponentAction::Select(
|
||||||
|
self.selected_item,
|
||||||
|
self.values
|
||||||
|
.get(self.selected_item)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or(LiveValue::None),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
// self.set_closed(cx);
|
||||||
|
self.draw_bg.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
|
Hit::FingerDown(_fe) => {
|
||||||
|
cx.set_key_focus(self.draw_bg.area());
|
||||||
|
// self.toggle_open(cx);
|
||||||
|
self.animator_play(cx, id!(hover.pressed));
|
||||||
|
}
|
||||||
|
Hit::FingerHoverIn(_) => {
|
||||||
|
cx.set_cursor(MouseCursor::Hand);
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
}
|
||||||
|
Hit::FingerHoverOut(_) => {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
Hit::FingerUp(fe) => {
|
||||||
|
if fe.is_over {
|
||||||
|
if fe.device.has_hovers() {
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
// cx.clear_sweep_lock(self.draw_bg.area());
|
||||||
|
|
||||||
|
self.draw_bg.begin(cx, walk, self.layout);
|
||||||
|
//let start_pos = cx.turtle().rect().pos;
|
||||||
|
self.draw_icon.draw_walk(cx, self.icon_walk);
|
||||||
|
self.draw_bg.end(cx);
|
||||||
|
|
||||||
|
// cx.add_nav_stop(self.draw_bg.area(), NavRole::DropDown, Margin::default());
|
||||||
|
|
||||||
|
if self.choices.is_some() {
|
||||||
|
// cx.set_sweep_lock(self.draw_bg.area());
|
||||||
|
let global = cx.global::<ChoicesGlobal>().clone();
|
||||||
|
let mut map = global.map.borrow_mut();
|
||||||
|
let popup_menu = map.get_mut(&self.choices.unwrap()).unwrap();
|
||||||
|
|
||||||
|
popup_menu.begin(cx);
|
||||||
|
|
||||||
|
for (i, item) in self.labels.iter().enumerate() {
|
||||||
|
let node_id = LiveId(i as u64).into();
|
||||||
|
popup_menu.draw_item(cx, node_id, item, walk);
|
||||||
|
}
|
||||||
|
|
||||||
|
popup_menu.end(cx, self.draw_bg.area());
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChoicesComponentRef {
|
||||||
|
pub fn item_clicked(&mut self, item_id: &[LiveId], actions: &Actions) -> bool {
|
||||||
|
if let Some(item) = actions.find_widget_action(self.widget_uid()) {
|
||||||
|
if let ChoicesComponentAction::Select(_id, value) = item.cast() {
|
||||||
|
return LiveValue::Bool(true) == value.enum_eq(item_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Live, LiveHook, LiveRegister)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct DrawStepsNav {
|
||||||
|
#[deref]
|
||||||
|
draw_super: DrawQuad,
|
||||||
|
#[live]
|
||||||
|
check_type: CheckType,
|
||||||
|
#[live]
|
||||||
|
hover: f32,
|
||||||
|
#[live]
|
||||||
|
focus: f32,
|
||||||
|
#[live]
|
||||||
|
selected: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, LiveHook, Widget)]
|
||||||
|
pub struct StepsNav {
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
icon_walk: Walk,
|
||||||
|
#[live]
|
||||||
|
label_walk: Walk, //
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_name: DrawText, //
|
||||||
|
#[live]
|
||||||
|
label_align: Align, //
|
||||||
|
|
||||||
|
#[redraw]
|
||||||
|
#[live]
|
||||||
|
draw_check: DrawStepsNav, //
|
||||||
|
#[live]
|
||||||
|
draw_text: DrawText,
|
||||||
|
#[live]
|
||||||
|
draw_icon: DrawIcon,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
text: RcStringMut, //
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
bind: String, //
|
||||||
|
}
|
||||||
|
#[derive(Clone, Debug, Default, Eq, Hash, Copy, PartialEq, FromLiveId)]
|
||||||
|
pub struct StepsNavId(pub LiveId);
|
||||||
|
|
||||||
|
#[derive(Live, LiveHook, LiveRegister)]
|
||||||
|
#[live_ignore]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum CheckType {
|
||||||
|
#[pick]
|
||||||
|
Check = shader_enum(1),
|
||||||
|
Radio = shader_enum(2),
|
||||||
|
Toggle = shader_enum(3),
|
||||||
|
None = shader_enum(4),
|
||||||
|
Bar = shader_enum(5), //RadioType::Bar
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[derive(Clone, Debug, DefaultNone)]
|
||||||
|
// pub enum StepsNavAction {
|
||||||
|
// Change(bool),
|
||||||
|
// None,
|
||||||
|
// }
|
||||||
|
#[derive(Default, Clone, Debug)]
|
||||||
|
pub enum StepsNavAction {
|
||||||
|
Change(bool),
|
||||||
|
WasSweeped,
|
||||||
|
WasSelected,
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
#[derive(Clone, DefaultNone, Debug)]
|
||||||
|
pub enum ChoicesAction {
|
||||||
|
WasSweeped(StepsNavId),
|
||||||
|
WasSelected(StepsNavId),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StepsNav {
|
||||||
|
pub fn draw_walk(&mut self, cx: &mut Cx2d, walk: Walk) {
|
||||||
|
self.draw_check.begin(cx, walk, self.layout);
|
||||||
|
// self.draw_icon.svg_file = icon;
|
||||||
|
|
||||||
|
self.draw_text
|
||||||
|
.draw_walk(cx, self.label_walk, self.label_align, self.text.as_ref());
|
||||||
|
self.draw_icon.draw_walk(cx, self.icon_walk);
|
||||||
|
self.draw_check.end(cx);
|
||||||
|
}
|
||||||
|
pub fn handle_event_with(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx,
|
||||||
|
event: &Event,
|
||||||
|
sweep_area: Area,
|
||||||
|
dispatch_action: &mut dyn FnMut(&mut Cx, StepsNavAction),
|
||||||
|
) {
|
||||||
|
if self.animator_handle_event(cx, event).must_redraw() {
|
||||||
|
// self.draw_bg.area().redraw(cx);
|
||||||
|
self.draw_check.area().redraw(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
match event.hits_with_options(
|
||||||
|
cx,
|
||||||
|
// self.draw_bg.area(),
|
||||||
|
self.draw_check.area(),
|
||||||
|
HitOptions::new().with_sweep_area(sweep_area),
|
||||||
|
) {
|
||||||
|
Hit::FingerHoverIn(_) => {
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
}
|
||||||
|
Hit::FingerHoverOut(_) => {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
Hit::FingerDown(_) => {
|
||||||
|
dispatch_action(cx, StepsNavAction::WasSweeped);
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
self.animator_play(cx, id!(select.on));
|
||||||
|
}
|
||||||
|
Hit::FingerUp(se) => {
|
||||||
|
if !se.is_sweep {
|
||||||
|
dispatch_action(cx, StepsNavAction::WasSelected);
|
||||||
|
} else {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
self.animator_play(cx, id!(select.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for StepsNav {
|
||||||
|
fn widget_to_data(
|
||||||
|
&self,
|
||||||
|
_cx: &mut Cx,
|
||||||
|
actions: &Actions,
|
||||||
|
nodes: &mut LiveNodeVec,
|
||||||
|
path: &[LiveId],
|
||||||
|
) -> bool {
|
||||||
|
match actions.find_widget_action_cast(self.widget_uid()) {
|
||||||
|
StepsNavAction::Change(v) => {
|
||||||
|
nodes.write_field_value(path, LiveValue::Bool(v));
|
||||||
|
true
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn data_to_widget(&mut self, cx: &mut Cx, nodes: &[LiveNode], path: &[LiveId]) {
|
||||||
|
if let Some(value) = nodes.read_field_value(path) {
|
||||||
|
if let Some(value) = value.as_bool() {
|
||||||
|
self.animator_toggle(cx, value, Animate::Yes, id!(selected.on), id!(selected.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
let uid = self.widget_uid();
|
||||||
|
self.animator_handle_event(cx, event);
|
||||||
|
|
||||||
|
match event.hits(cx, self.draw_check.area()) {
|
||||||
|
Hit::FingerHoverIn(_) => {
|
||||||
|
cx.set_cursor(MouseCursor::Hand);
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
}
|
||||||
|
Hit::FingerHoverOut(_) => {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
Hit::FingerDown(_fe) => {
|
||||||
|
if self.animator_in_state(cx, id!(selected.on)) {
|
||||||
|
self.animator_play(cx, id!(selected.off));
|
||||||
|
cx.widget_action(uid, &scope.path, StepsNavAction::Change(false));
|
||||||
|
} else {
|
||||||
|
self.animator_play(cx, id!(selected.on));
|
||||||
|
cx.widget_action(uid, &scope.path, StepsNavAction::Change(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Hit::FingerUp(_fe) => {}
|
||||||
|
Hit::FingerMove(_fe) => {}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
self.draw_walk(cx, walk);
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn text(&self) -> String {
|
||||||
|
self.text.as_ref().to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_text(&mut self, v: &str) {
|
||||||
|
self.text.as_mut_empty().push_str(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone)]
|
||||||
|
struct ChoicesGlobal {
|
||||||
|
map: Rc<RefCell<ComponentMap<LivePtr, Choices>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, LiveRegister, WidgetWrap)]
|
||||||
|
pub struct Choices {
|
||||||
|
#[live]
|
||||||
|
draw_list: DrawList2d,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
choice_item: Option<LivePtr>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_bg: DrawQuad,
|
||||||
|
#[live]
|
||||||
|
#[redraw]
|
||||||
|
draw_icon: DrawIcon,
|
||||||
|
#[live]
|
||||||
|
icon_walk: Walk,
|
||||||
|
|
||||||
|
#[layout]
|
||||||
|
layout: Layout,
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
labels: Vec<String>,
|
||||||
|
#[live]
|
||||||
|
values: Vec<LiveValue>,
|
||||||
|
|
||||||
|
#[live]
|
||||||
|
items: Vec<String>,
|
||||||
|
#[rust]
|
||||||
|
choice_items: ComponentMap<StepsNavId, StepsNav>,
|
||||||
|
#[rust]
|
||||||
|
init_select_item: Option<StepsNavId>,
|
||||||
|
#[rust]
|
||||||
|
first_tap: bool,
|
||||||
|
#[rust]
|
||||||
|
count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for Choices {
|
||||||
|
fn after_apply(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) {
|
||||||
|
if let Some(index) = nodes.child_by_name(index, live_id!(list_node).as_field()) {
|
||||||
|
for (_, node) in self.choice_items.iter_mut() {
|
||||||
|
node.apply(cx, apply, index, nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.draw_list.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for Choices {
|
||||||
|
fn handle_event(&mut self, _cx: &mut Cx, _event: &Event, _scope: &mut Scope) {}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
self.draw_bg.begin(cx, walk, self.layout);
|
||||||
|
self.draw_icon.draw_walk(cx, self.icon_walk);
|
||||||
|
self.draw_bg.end(cx);
|
||||||
|
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Choices {
|
||||||
|
pub fn menu_contains_pos(&self, cx: &mut Cx, pos: DVec2) -> bool {
|
||||||
|
self.draw_bg.area().clipped_rect(cx).contains(pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn begin(&mut self, cx: &mut Cx2d) {
|
||||||
|
self.draw_list.begin_overlay_reuse(cx);
|
||||||
|
|
||||||
|
cx.begin_pass_sized_turtle(Layout::flow_down());
|
||||||
|
|
||||||
|
self.draw_bg.begin(cx, self.walk, self.layout);
|
||||||
|
self.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn end(&mut self, cx: &mut Cx2d, shift_area: Area) {
|
||||||
|
self.draw_bg.end(cx);
|
||||||
|
let area = self.draw_bg.area().rect(cx);
|
||||||
|
let shift = DVec2 {
|
||||||
|
x: -area.size.x + (shift_area.rect(cx).size.x * 0.7),
|
||||||
|
y: 30.,
|
||||||
|
};
|
||||||
|
|
||||||
|
cx.end_pass_sized_turtle_with_shift(shift_area, shift);
|
||||||
|
self.draw_list.end(cx);
|
||||||
|
|
||||||
|
self.choice_items.retain_visible();
|
||||||
|
if let Some(init_select_item) = self.init_select_item.take() {
|
||||||
|
self.select_item_state(cx, init_select_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_item(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx2d,
|
||||||
|
item_id: StepsNavId,
|
||||||
|
label: &str,
|
||||||
|
// icon: LiveDependency,
|
||||||
|
walk: Walk,
|
||||||
|
) {
|
||||||
|
self.count += 1;
|
||||||
|
|
||||||
|
let menu_item = self.choice_item;
|
||||||
|
let menu_item = self
|
||||||
|
.choice_items
|
||||||
|
.get_or_insert(cx, item_id, |cx| StepsNav::new_from_ptr(cx, menu_item));
|
||||||
|
// menu_item.draw_walk(cx, label, icon);
|
||||||
|
menu_item.draw_walk(cx, walk);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_select_item(&mut self, which_id: StepsNavId) {
|
||||||
|
self.init_select_item = Some(which_id);
|
||||||
|
self.first_tap = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn select_item_state(&mut self, cx: &mut Cx, which_id: StepsNavId) {
|
||||||
|
for (id, item) in &mut *self.choice_items {
|
||||||
|
if *id == which_id {
|
||||||
|
item.animator_cut(cx, id!(select.on));
|
||||||
|
item.animator_cut(cx, id!(hover.on));
|
||||||
|
} else {
|
||||||
|
item.animator_cut(cx, id!(select.off));
|
||||||
|
item.animator_cut(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_event_with(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx,
|
||||||
|
event: &Event,
|
||||||
|
sweep_area: Area,
|
||||||
|
dispatch_action: &mut dyn FnMut(&mut Cx, ChoicesAction),
|
||||||
|
) {
|
||||||
|
let mut actions = Vec::new();
|
||||||
|
for (item_id, node) in self.choice_items.iter_mut() {
|
||||||
|
node.handle_event_with(cx, event, sweep_area, &mut |_, e| {
|
||||||
|
actions.push((*item_id, e))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (node_id, action) in actions {
|
||||||
|
match action {
|
||||||
|
StepsNavAction::WasSweeped => {
|
||||||
|
self.select_item_state(cx, node_id);
|
||||||
|
dispatch_action(cx, ChoicesAction::WasSweeped(node_id));
|
||||||
|
}
|
||||||
|
StepsNavAction::WasSelected => {
|
||||||
|
self.select_item_state(cx, node_id);
|
||||||
|
dispatch_action(cx, ChoicesAction::WasSelected(node_id));
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -55,13 +55,18 @@ live_design! {
|
||||||
|
|
||||||
COLOR_DOWN_FULL = #000
|
COLOR_DOWN_FULL = #000
|
||||||
|
|
||||||
COLOR_DOWN_0 = #x00000000
|
// COLOR_DOWN_0 = #x00000000
|
||||||
|
// COLOR_DOWN_0 = #x00bbd3
|
||||||
|
COLOR_DOWN_0 = #x1c1c1c
|
||||||
COLOR_DOWN_1 = #x00000011
|
COLOR_DOWN_1 = #x00000011
|
||||||
COLOR_DOWN_2 = #x00000022
|
COLOR_DOWN_2 = #x00000022
|
||||||
COLOR_DOWN_3 = #x00000044
|
COLOR_DOWN_3 = #x00000044
|
||||||
COLOR_DOWN_4 = #x00000066
|
COLOR_DOWN_4 = #x00000066
|
||||||
|
// COLOR_DOWN_4 = #016def
|
||||||
|
// COLOR_DOWN_4 = #x086975
|
||||||
COLOR_DOWN_5 = #x000000AA
|
COLOR_DOWN_5 = #x000000AA
|
||||||
COLOR_DOWN_6 = #x000000CC
|
COLOR_DOWN_6 = #x000000CC
|
||||||
|
COLOR_DOWN_7 = #x00bbd3
|
||||||
|
|
||||||
COLOR_UP_0 = #xFFFFFF00
|
COLOR_UP_0 = #xFFFFFF00
|
||||||
COLOR_UP_1 = #xFFFFFF0A
|
COLOR_UP_1 = #xFFFFFF0A
|
||||||
|
|
|
@ -1,5 +1,20 @@
|
||||||
|
// #![allow(unused)]
|
||||||
|
// #![cfg(target_arch = "wasm32")]
|
||||||
|
// use makepad_wasm_bridge::*;
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
// pub fn get_current_year() -> i32 {
|
||||||
|
// let now = SystemTime::now();
|
||||||
|
// let since_the_epoch = now.duration_since(UNIX_EPOCH).expect("Time went backwards");
|
||||||
|
// let in_seconds = since_the_epoch.as_secs();
|
||||||
|
// let seconds_per_year = 60 * 60 * 24 * 365;
|
||||||
|
// let current_year = 1970 + (in_seconds / seconds_per_year as u64) as i32;
|
||||||
|
// current_year
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
pub fn get_current_year() -> i32 {
|
pub fn get_current_year() -> i32 {
|
||||||
let now = SystemTime::now();
|
let now = SystemTime::now();
|
||||||
let since_the_epoch = now.duration_since(UNIX_EPOCH).expect("Time went backwards");
|
let since_the_epoch = now.duration_since(UNIX_EPOCH).expect("Time went backwards");
|
||||||
|
|