choices options UI

This commit is contained in:
aOK 2024-05-14 09:40:13 +03:00
parent 0adbfdf84c
commit a817794709
35 changed files with 5459 additions and 92 deletions

BIN
nimanyatta_v001/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -1,3 +1,4 @@
/dist/
/target/
/Cargo.lock
extra.txt

View file

@ -3,5 +3,23 @@ name = "nimanyatta_v001"
version = "0.1.0"
edition = "2021"
[lib]
name = "nimanyatta_v001"
crate-type = ["staticlib", "cdylib", "rlib"]
[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"]

View file

@ -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

Binary file not shown.

View 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<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"/>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 477 B

After

Width:  |  Height:  |  Size: 478 B

View 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

View 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

View 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

View file

@ -1,4 +1,6 @@
// use crate::shared::stack_view_action::StackViewAction;
use makepad_widgets::*;
// use std::collections::HashMap;
live_design! {
@ -7,12 +9,20 @@ live_design! {
import makepad_widgets::theme_desktop_dark::*;
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::three::three_screen::ThreeScreen;
import crate::four::four_screen::FourScreen;
import crate::five::five_screen::FiveScreen;
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 = {
font_size: (12),
@ -21,7 +31,7 @@ live_design! {
ICON_CHAT = dep("crate://self/resources/icons/chat.svg")
PHONE_CHAT = dep("crate://self/resources/icons/chat.svg")
AppTab = <RadioButton> {
AppTab2 = <RadioButton> {
width: Fit,
height: Fill,
flow: Right,
@ -31,8 +41,43 @@ live_design! {
// color: #000
draw_radio: {
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: {
color_selected: #000, //#0b0,
@ -41,9 +86,114 @@ live_design! {
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}} {
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 = {
show_bg: true
@ -80,31 +230,36 @@ live_design! {
}
mobile_modes = <View> {
home_tab = <AppTab> {
flow: Right,
align: {x: 0.0, y: 0.5}
animator: {selected = {default: on}}
label: ""
draw_icon: {
svg_file: (ICON_CHAT),
fn get_color(self) -> vec4 {
return mix(
#000,
#016def,//#0b0,
self.selected
)
// spacing: 20
<View> {
// padding: { right: 60 }
home_tab = <AppTab> {
flow: Right,
align: {x: 0.0, y: 0.5}
animator: {selected = {default: on}}
text: ""
draw_icon: {
svg_file: (ICON_CHAT),
fn get_color(self) -> vec4 {
return mix(
#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> {
flow: Right,
align: {x: 0.0, y: 0.5}
animator: {selected = {default: on}}
label: "2"
// animator: {selected = {default: on}}
text: "2"
draw_icon: {
svg_file: (ICON_CHAT),
fn get_color(self) -> vec4 {
@ -115,15 +270,18 @@ live_design! {
)
}
}
width: Fill,
width: 80.0,
icon_walk: {width: 20, height: 20}
flow: Down, spacing: 5.0, align: {x: 0.5, y: 0.5}
}
}
<View> {
align: {x: 0.5}
three_tab = <AppTab> {
flow: Right,
align: {x: 0.0, y: 0.5}
animator: {selected = {default: on}}
label: "3"
// animator: {selected = {default: on}}
text: "3"
draw_icon: {
svg_file: (ICON_CHAT),
fn get_color(self) -> vec4 {
@ -134,15 +292,18 @@ live_design! {
)
}
}
width: Fill,
width: 80.0,
icon_walk: {width: 20, height: 20}
flow: Down, spacing: 5.0, align: {x: 0.5, y: 0.5}
}
}
<View> {
align: {x: 0.5}
four_tab = <AppTab> {
flow: Right,
align: {x: 0.0, y: 0.5}
animator: {selected = {default: on}}
label: "4"
// animator: {selected = {default: on}}
text: "4"
draw_icon: {
svg_file: (ICON_CHAT),
fn get_color(self) -> vec4 {
@ -153,28 +314,32 @@ live_design! {
)
}
}
width: Fill,
width: 80.0,
icon_walk: {width: 20, height: 20}
flow: Down, spacing: 5.0, align: {x: 0.5, y: 0.5}
}
}
<View> {
align: {x: 1.0}
five_tab = <AppTab> {
flow: Right,
align: {x: 0.0, y: 0.5}
animator: {selected = {default: on}}
label: ""
draw_icon: {
svg_file: (PHONE_CHAT),
fn get_color(self) -> vec4 {
return mix(
#000,
#016def,//#0b0,
self.selected
)
flow: Right,
align: {x: 0.0, y: 0.5}
// animator: {selected = {default: on}}
text: ""
draw_icon: {
svg_file: (PHONE_CHAT),
fn get_color(self) -> vec4 {
return mix(
#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.8, y: 0.5}
}
}
@ -184,10 +349,10 @@ live_design! {
padding: 0.0
home_frame = <HomeScreen> { visible: true }
kimanyatta_frame = <TwoScreen> {visible: false}
insurance_frame = <ThreeScreen> {visible: false}
matatu_frame = <FourScreen> {visible: false}
contactus_frame = <FiveScreen> {visible: false}
two_frame = <TwoScreen> {visible: false}
three_frame = <ThreeScreen> {visible: false}
four_frame = <FourScreen> {visible: false}
five_frame = <FiveScreen> {visible: false}
}
}
@ -197,12 +362,15 @@ live_design! {
title_container = {
title = {
text: "Help Me Choose"
draw_text: {
color: #000
}
}
}
}
}
body = {
<DefaultChoiceScreen> {}
<DefaultChoice> {}
}
}
}
@ -217,6 +385,8 @@ app_main!(App);
pub struct App {
#[live]
ui: WidgetRef,
// #[rust]
// navigation_destinations: HashMap<StackViewAction, LiveId>,
}
impl LiveRegister for App {
@ -224,6 +394,8 @@ impl LiveRegister for App {
crate::makepad_widgets::live_design(cx);
crate::home::home_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::three::three_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::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 {
// 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) {
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));
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());
}
}
// 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);
// }
}

View 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
);
}
}

View 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),