changes to app_web.rs
This commit is contained in:
parent
dc1efaeed6
commit
8d9de58378
15 changed files with 891 additions and 46 deletions
14
src/app.rs
14
src/app.rs
|
@ -1,5 +1,7 @@
|
||||||
use makepad_widgets::*;
|
use makepad_widgets::*;
|
||||||
|
|
||||||
|
use crate::data::state::State;
|
||||||
|
|
||||||
live_design! {
|
live_design! {
|
||||||
import makepad_widgets::base::*;
|
import makepad_widgets::base::*;
|
||||||
import makepad_widgets::theme_desktop_dark::*;
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
@ -32,6 +34,8 @@ app_main!(App);
|
||||||
pub struct App {
|
pub struct App {
|
||||||
#[live]
|
#[live]
|
||||||
ui: WidgetRef,
|
ui: WidgetRef,
|
||||||
|
#[rust]
|
||||||
|
state: State,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LiveRegister for App {
|
impl LiveRegister for App {
|
||||||
|
@ -46,14 +50,20 @@ impl LiveRegister for App {
|
||||||
crate::shared::live_design(cx);
|
crate::shared::live_design(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MatchEvent for App {
|
impl MatchEvent for App {
|
||||||
fn handle_actions(&mut self, _cx: &mut Cx, _actions: &Actions) {}
|
fn handle_actions(&mut self, _cx: &mut Cx, _actions: &Actions) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppMain for App {
|
impl AppMain for App {
|
||||||
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
||||||
|
self.ui
|
||||||
|
.handle_event(cx, event, &mut Scope::with_data(&mut self.state));
|
||||||
self.match_event(cx, event);
|
self.match_event(cx, event);
|
||||||
self.ui.handle_event(cx, event, &mut Scope::empty());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// impl AppMain for App {
|
||||||
|
// fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
||||||
|
// self.match_event(cx, event);
|
||||||
|
// self.ui.handle_event(cx, event, &mut Scope::empty());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use makepad_widgets::*;
|
use makepad_widgets::*;
|
||||||
|
|
||||||
|
use crate::data::state::State;
|
||||||
|
|
||||||
live_design! {
|
live_design! {
|
||||||
import makepad_widgets::base::*;
|
import makepad_widgets::base::*;
|
||||||
import makepad_widgets::theme_desktop_dark::*;
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
@ -45,55 +49,74 @@ pub struct AppUI {
|
||||||
view: View,
|
view: View,
|
||||||
|
|
||||||
#[rust]
|
#[rust]
|
||||||
screen_width: f64,
|
state: State,
|
||||||
|
// #[rust]
|
||||||
|
// screen_width: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LiveHook for AppUI {
|
impl LiveHook for AppUI {
|
||||||
fn after_new_from_doc(&mut self, cx: &mut Cx) {
|
fn after_new_from_doc(&mut self, cx: &mut Cx) {
|
||||||
let mobile_screen = self.view.view(id!(mobile));
|
let mobile_screen = self.view.view(id!(mobile));
|
||||||
let web_screen = self.view.view(id!(web));
|
let web_screen = self.view.view(id!(web));
|
||||||
if self.screen_width < 960_f64 {
|
if self.state.screen_width < 960_f64 {
|
||||||
log!("SCREEN_WIDTH ===> {}", self.screen_width);
|
log!("SCREEN_WIDTH ===> {}", self.state.screen_width);
|
||||||
web_screen.set_visible(false);
|
web_screen.set_visible(false);
|
||||||
mobile_screen.set_visible_and_redraw(cx, true);
|
mobile_screen.set_visible_and_redraw(cx, true);
|
||||||
// web_screen.draw_all(cx, &mut Scope::empty());
|
// web_screen.draw_all(cx, &mut Scope::empty());
|
||||||
} else if self.screen_width > 960_f64 {
|
} else if self.state.screen_width > 960_f64 {
|
||||||
mobile_screen.set_visible(false);
|
mobile_screen.set_visible(false);
|
||||||
web_screen.set_visible_and_redraw(cx, true);
|
web_screen.set_visible_and_redraw(cx, true);
|
||||||
// web_screen.draw_all(cx, &mut Scope::empty());
|
// web_screen.draw_all(cx, &mut Scope::empty());
|
||||||
} else {
|
} else {
|
||||||
log!("SCREEN_WIDTH ===> {}", self.screen_width);
|
log!("SCREEN_WIDTH ===> {}", self.state.screen_width);
|
||||||
}
|
}
|
||||||
|
// Image directory
|
||||||
|
let home = std::env::var("HOME")
|
||||||
|
.or_else(|_| std::env::var("USERPROFILE"))
|
||||||
|
.expect("home not found");
|
||||||
|
|
||||||
|
self.state.load_images(&Path::new(&home).join("Downloads"));
|
||||||
}
|
}
|
||||||
|
// fn handle_startup(&mut self, _cx: &mut Cx) {
|
||||||
|
// let home = std::env::var("HOME")
|
||||||
|
// .or_else(|_| std::env::var("USERPROFILE"))
|
||||||
|
// .expect("home not found");
|
||||||
|
|
||||||
|
// self.state.load_images(&Path::new(&home).join("Downloads"));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Widget for AppUI {
|
impl Widget for AppUI {
|
||||||
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
self.view.handle_event(cx, event, scope);
|
self.view
|
||||||
|
.handle_event(cx, event, &mut Scope::with_data(&mut self.state));
|
||||||
|
// self.view.handle_event(cx, event, scope);
|
||||||
self.widget_match_event(cx, event, scope);
|
self.widget_match_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 {
|
||||||
// DrawStep::done()
|
// DrawStep::done()
|
||||||
|
// let state = scope.data.get::<State>().unwrap();
|
||||||
let mobile_screen = self.view.view(id!(mobile));
|
let mobile_screen = self.view.view(id!(mobile));
|
||||||
let web_screen = self.view.view(id!(web));
|
let web_screen = self.view.view(id!(web));
|
||||||
|
|
||||||
while let Some(_next) = self.view.draw(cx, &mut Scope::empty()).step() {
|
while let Some(_next) = self.view.draw(cx, scope).step() {
|
||||||
// if let Some(mut mobile_screen) = mobile_screen.has_widget(&next).borrow_mut() {}
|
// if let Some(mut mobile_screen) = mobile_screen.has_widget(&next).borrow_mut() {}
|
||||||
if self.screen_width == 0_f64 {
|
if self.state.screen_width == 0_f64 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if self.screen_width < 960_f64 {
|
// if self.state.screen_width < 960_f64 {
|
||||||
|
if self.state.screen_width < 960_f64 {
|
||||||
web_screen.set_visible(false);
|
web_screen.set_visible(false);
|
||||||
mobile_screen.set_visible_and_redraw(cx, true);
|
mobile_screen.set_visible_and_redraw(cx, true);
|
||||||
mobile_screen.draw_all(cx, &mut Scope::empty());
|
mobile_screen.draw_all(cx, scope);
|
||||||
self.view.draw_walk(cx, scope, walk)?;
|
self.view.draw_walk(cx, scope, walk)?;
|
||||||
} else if self.screen_width > 960_f64 {
|
} else if self.state.screen_width > 960_f64 {
|
||||||
mobile_screen.set_visible(false);
|
mobile_screen.set_visible(false);
|
||||||
web_screen.set_visible_and_redraw(cx, true);
|
web_screen.set_visible_and_redraw(cx, true);
|
||||||
web_screen.draw_all(cx, &mut Scope::empty());
|
web_screen.draw_all(cx, scope);
|
||||||
self.view.draw_walk(cx, scope, walk)?;
|
self.view.draw_walk(cx, scope, walk)?;
|
||||||
} else {
|
} else {
|
||||||
log!("ESLE_SCREEN_WIDTH ===> {}", self.screen_width);
|
log!("ESLE_SCREEN_WIDTH ===> {}", self.state.screen_width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DrawStep::done()
|
DrawStep::done()
|
||||||
|
@ -101,20 +124,21 @@ impl Widget for AppUI {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetMatchEvent for AppUI {
|
impl WidgetMatchEvent for AppUI {
|
||||||
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, _scope: &mut Scope) {
|
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, scope: &mut Scope) {
|
||||||
|
let state = scope.data.get_mut::<State>().unwrap();
|
||||||
for action in actions {
|
for action in actions {
|
||||||
if let WindowAction::WindowGeomChange(ce) = action.as_widget_action().cast() {
|
if let WindowAction::WindowGeomChange(ce) = action.as_widget_action().cast() {
|
||||||
self.screen_width = ce.new_geom.inner_size.x * ce.new_geom.dpi_factor;
|
state.screen_width = ce.new_geom.inner_size.x * ce.new_geom.dpi_factor;
|
||||||
let mobile_screen = self.view.view(id!(mobile));
|
let mobile_screen = self.view.view(id!(mobile));
|
||||||
let web_screen = self.view.view(id!(web));
|
let web_screen = self.view.view(id!(web));
|
||||||
if self.screen_width < 960_f64 {
|
if state.screen_width < 960_f64 {
|
||||||
web_screen.set_visible(false);
|
web_screen.set_visible(false);
|
||||||
mobile_screen.set_visible_and_redraw(cx, true);
|
mobile_screen.set_visible_and_redraw(cx, true);
|
||||||
} else if self.screen_width > 960_f64 {
|
} else if state.screen_width > 960_f64 {
|
||||||
mobile_screen.set_visible(false);
|
mobile_screen.set_visible(false);
|
||||||
web_screen.set_visible_and_redraw(cx, true);
|
web_screen.set_visible_and_redraw(cx, true);
|
||||||
} else {
|
} else {
|
||||||
log!("ELSE_SCREEN_WIDTH ===> {}", self.screen_width);
|
log!("ELSE_SCREEN_WIDTH ===> {}", state.screen_width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
use makepad_widgets::*;
|
use makepad_widgets::*;
|
||||||
|
|
||||||
|
use crate::data::state::State;
|
||||||
|
|
||||||
live_design! {
|
live_design! {
|
||||||
import makepad_widgets::base::*;
|
import makepad_widgets::base::*;
|
||||||
import makepad_widgets::theme_desktop_dark::*;
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
@ -52,32 +54,71 @@ live_design! {
|
||||||
margin: 0.0,
|
margin: 0.0,
|
||||||
padding: 0.0,
|
padding: 0.0,
|
||||||
flow: Down,
|
flow: Down,
|
||||||
width: Fit,
|
width: Fill,
|
||||||
height: Fit,
|
height: Fill,
|
||||||
// debug: A
|
// debug: A
|
||||||
|
|
||||||
home_screen_frame = <HomeScreen> {visible: true}
|
home_screen_frame = <HomeScreen> {align: {x: 0.5, y: 0.5}, visible: true}
|
||||||
aboutus_screen_frame = <AboutUs> {visible: false}
|
aboutus_screen_frame = <AboutUs> {visible: false}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Live, LiveHook, Widget)]
|
#[derive(Live)]
|
||||||
pub struct AppWebUI {
|
pub struct AppWebUI {
|
||||||
#[deref]
|
#[live]
|
||||||
view: View,
|
view: WidgetRef,
|
||||||
}
|
}
|
||||||
impl Widget for AppWebUI {
|
|
||||||
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
impl LiveRegister for AppWebUI {
|
||||||
self.view.handle_event(cx, event, scope);
|
fn live_register(cx: &mut Cx) {
|
||||||
self.widget_match_event(cx, event, scope);
|
crate::makepad_widgets::live_design(cx);
|
||||||
|
crate::app_ui::live_design(cx);
|
||||||
|
crate::app_mobile::live_design(cx);
|
||||||
|
// crate::app_web::live_design(cx);
|
||||||
|
|
||||||
|
crate::home::live_design(cx);
|
||||||
|
crate::aboutus::live_design(cx);
|
||||||
|
crate::shared::live_design(cx);
|
||||||
}
|
}
|
||||||
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
}
|
||||||
// DrawStep::done()
|
impl LiveHook for AppWebUI {
|
||||||
self.view.draw_walk(cx, scope, walk)
|
fn after_new_from_doc(&mut self, _cx: &mut Cx) {
|
||||||
|
println!("after_new_from_doc(): starting some kind of a loop");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetMatchEvent for AppWebUI {
|
impl MatchEvent for AppWebUI {
|
||||||
fn handle_actions(&mut self, _cx: &mut Cx, _actions: &Actions, _scope: &mut Scope) {}
|
fn handle_draw_2d(&mut self, cx: &mut Cx2d) {
|
||||||
|
let navbar_menu = self.view.view(id!(navbar_menu));
|
||||||
|
while let Some(next) = self.view.draw(cx, &mut Scope::empty()).step() {
|
||||||
|
navbar_menu.draw_all(cx, &mut Scope::empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {
|
||||||
|
self.view
|
||||||
|
.radio_button_set(ids!(
|
||||||
|
navbar_menu.home_screen_tab,
|
||||||
|
navbar_menu.aboutus_screen_tab,
|
||||||
|
))
|
||||||
|
.selected_to_visible(
|
||||||
|
cx,
|
||||||
|
&self.view,
|
||||||
|
actions,
|
||||||
|
ids!(
|
||||||
|
application_pages.home_screen_frame,
|
||||||
|
application_pages.aboutus_screen_frame,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppMain for AppWebUI {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
||||||
|
if self.match_event_with_draw_2d(cx, event).is_ok() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self.match_event(cx, event);
|
||||||
|
self.view.handle_event(cx, event, &mut Scope::empty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
1
src/data/mod.rs
Normal file
1
src/data/mod.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod state;
|
27
src/data/state.rs
Normal file
27
src/data/state.rs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
use std::{
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct State {
|
||||||
|
pub images: Vec<PathBuf>,
|
||||||
|
pub screen_width: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub fn load_images(&mut self, path: &Path) {
|
||||||
|
self.images = fs::read_dir(path)
|
||||||
|
.expect("unable to read directory")
|
||||||
|
.map(|entry| entry.expect("unable to read entry").path())
|
||||||
|
.filter(|path| {
|
||||||
|
path.extension()
|
||||||
|
.map_or(false, |ext| ["png", "jpg"].iter().any(|e| *e == ext))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn root(&self) -> Option<&Path> {
|
||||||
|
self.images.first().map(|p| p.parent().unwrap())
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,7 +18,6 @@ live_design! {
|
||||||
height: Fill
|
height: Fill
|
||||||
padding: {left: 25, right: 25, bottom: 20},
|
padding: {left: 25, right: 25, bottom: 20},
|
||||||
|
|
||||||
|
|
||||||
<View>{
|
<View>{
|
||||||
flow: Down,
|
flow: Down,
|
||||||
spacing:10,
|
spacing:10,
|
||||||
|
@ -35,6 +34,8 @@ live_design! {
|
||||||
width: 100, height: 30
|
width: 100, height: 30
|
||||||
text: "Click to count "
|
text: "Click to count "
|
||||||
}
|
}
|
||||||
|
<View>{
|
||||||
|
scroll_bars: <ScrollBars> {show_scroll_x: false, show_scroll_y: true}
|
||||||
label1 = <Label> {
|
label1 = <Label> {
|
||||||
draw_text: {
|
draw_text: {
|
||||||
color: #f
|
color: #f
|
||||||
|
@ -47,6 +48,8 @@ live_design! {
|
||||||
// width: 400.0,
|
// width: 400.0,
|
||||||
width: Fill,
|
width: Fill,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,11 @@ live_design! {
|
||||||
HomeScreen = {{HomeScreen}} {
|
HomeScreen = {{HomeScreen}} {
|
||||||
width: Fill,
|
width: Fill,
|
||||||
height: Fill,
|
height: Fill,
|
||||||
spacing: 10,
|
spacing: 10.0,
|
||||||
|
|
||||||
<View> {
|
<View> {
|
||||||
|
debug: A
|
||||||
|
|
||||||
<View> {
|
<View> {
|
||||||
width: Fill,
|
width: Fill,
|
||||||
height: Fill,
|
height: Fill,
|
||||||
|
|
|
@ -3,6 +3,7 @@ pub mod app;
|
||||||
pub mod app_mobile;
|
pub mod app_mobile;
|
||||||
pub mod app_ui;
|
pub mod app_ui;
|
||||||
pub mod app_web;
|
pub mod app_web;
|
||||||
|
pub mod data;
|
||||||
|
|
||||||
pub mod aboutus;
|
pub mod aboutus;
|
||||||
pub mod home;
|
pub mod home;
|
||||||
|
|
0
src/shared/editor/block_delete_button.rs
Normal file
0
src/shared/editor/block_delete_button.rs
Normal file
0
src/shared/editor/block_header_button.rs
Normal file
0
src/shared/editor/block_header_button.rs
Normal file
121
src/shared/editor/fish_block_editor.rs
Normal file
121
src/shared/editor/fish_block_editor.rs
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
use crate::makepad_widgets::*;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
import makepad_draw::shader::std::*;
|
||||||
|
import crate::fish_theme::*;
|
||||||
|
import crate::block_header_button::*;
|
||||||
|
import crate::block_delete_button::*;
|
||||||
|
|
||||||
|
FishBlockEditor = <View>
|
||||||
|
{
|
||||||
|
margin: 0
|
||||||
|
width: 200
|
||||||
|
height: Fit
|
||||||
|
flow: Down
|
||||||
|
optimize: DrawList
|
||||||
|
|
||||||
|
title = <View>
|
||||||
|
{
|
||||||
|
show_bg: true
|
||||||
|
flow: Down
|
||||||
|
width: Fill
|
||||||
|
height: Fit
|
||||||
|
padding: 0
|
||||||
|
draw_bg:
|
||||||
|
{
|
||||||
|
fn pixel(self) -> vec4
|
||||||
|
{
|
||||||
|
return mix(vec4(1,1,0.6,1), vec4(1,1,0.5,1),self.pos.y);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
topbar = <View>
|
||||||
|
{
|
||||||
|
flow:Right,
|
||||||
|
height: Fit,
|
||||||
|
header = <BlockHeaderButton>
|
||||||
|
{
|
||||||
|
draw_text:
|
||||||
|
{
|
||||||
|
color: #0
|
||||||
|
text_style: <H2_TEXT_BOLD> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete = <BlockDeleteButton>
|
||||||
|
{
|
||||||
|
width: Fit,
|
||||||
|
draw_text:
|
||||||
|
{
|
||||||
|
color: #0
|
||||||
|
text_style: <H2_TEXT_BOLD> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
padding = <View>
|
||||||
|
{
|
||||||
|
width: 20
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
body = <View>
|
||||||
|
{
|
||||||
|
show_bg: true
|
||||||
|
width: Fill
|
||||||
|
height: Fit
|
||||||
|
flow: Down
|
||||||
|
padding: {left: 30, right: 30, top: 4, bottom: 4}
|
||||||
|
|
||||||
|
draw_bg: {
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
return mix(vec4(1,1,0.9,1), vec4(1,1,0.8,1),self.pos.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
<FishSlider>{text:"Slider A"}
|
||||||
|
<FishSlider>{text:"Slider B"}
|
||||||
|
<FishSlider>{text:"Slider C"}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FishBlockEditorGenerator = <FishBlockEditor>
|
||||||
|
{
|
||||||
|
title = {draw_bg: { fn pixel(self) -> vec4 { return mix(THEME_COLOR_GENERATOR, THEME_COLOR_GENERATOR_DARK, self.pos.y) }} }
|
||||||
|
body = {draw_bg: { fn pixel(self) -> vec4 { return THEME_COLOR_GENERATOR_FADE} } }
|
||||||
|
}
|
||||||
|
|
||||||
|
FishBlockEditorEffect = <FishBlockEditor>
|
||||||
|
{
|
||||||
|
title = {draw_bg: { fn pixel(self) -> vec4 { return mix(THEME_COLOR_EFFECT, THEME_COLOR_EFFECT_DARK, self.pos.y) }} }
|
||||||
|
body = {draw_bg: { fn pixel(self) -> vec4 { return THEME_COLOR_EFFECT_FADE} } }
|
||||||
|
}
|
||||||
|
|
||||||
|
FishBlockEditorMeta = <FishBlockEditor>
|
||||||
|
{
|
||||||
|
title = {draw_bg: { fn pixel(self) -> vec4 { return mix(THEME_COLOR_META, THEME_COLOR_META_DARK, self.pos.y) }} }
|
||||||
|
body = {draw_bg: { fn pixel(self) -> vec4 { return THEME_COLOR_META_FADE} } }
|
||||||
|
}
|
||||||
|
|
||||||
|
FishBlockEditorUtility = <FishBlockEditor>
|
||||||
|
{
|
||||||
|
title = {draw_bg: { fn pixel(self) -> vec4 { return mix(THEME_COLOR_UTILITY, THEME_COLOR_UTILITY_DARK, self.pos.y) }} }
|
||||||
|
body = {draw_bg: { fn pixel(self) -> vec4 { return THEME_COLOR_UTILITY_FADE} } }
|
||||||
|
}
|
||||||
|
|
||||||
|
FishBlockEditorModulator = <FishBlockEditor>
|
||||||
|
{
|
||||||
|
title = {draw_bg: { fn pixel(self) -> vec4 { return mix(THEME_COLOR_MODULATION, THEME_COLOR_MODULATION_DARK, self.pos.y) }} }
|
||||||
|
body = {draw_bg: { fn pixel(self) -> vec4 { return THEME_COLOR_MODULATION_FADE} } }
|
||||||
|
}
|
||||||
|
|
||||||
|
FishBlockEditorEnvelope= <FishBlockEditor>
|
||||||
|
{
|
||||||
|
title = {draw_bg: { fn pixel(self) -> vec4 { return mix(THEME_COLOR_ENVELOPE, THEME_COLOR_ENVELOPE_DARK, self.pos.y) }} }
|
||||||
|
body = {draw_bg: { fn pixel(self) -> vec4 { return THEME_COLOR_ENVELOPE_FADE} } }
|
||||||
|
}
|
||||||
|
FishBlockEditorFilter= <FishBlockEditor>
|
||||||
|
{
|
||||||
|
title = {draw_bg: { fn pixel(self) -> vec4 { return mix(THEME_COLOR_FILTER, THEME_COLOR_FILTER_DARK, self.pos.y) }} }
|
||||||
|
body = {draw_bg: { fn pixel(self) -> vec4 { return THEME_COLOR_FILTER_FADE} } }
|
||||||
|
}
|
||||||
|
}
|
483
src/shared/editor/fish_patch_editor.rs
Normal file
483
src/shared/editor/fish_patch_editor.rs
Normal file
|
@ -0,0 +1,483 @@
|
||||||
|
use crate::{
|
||||||
|
// block_connector_button::BlockConnectorButtonAction,
|
||||||
|
// block_delete_button::BlockDeleteButtonAction, block_header_button::BlockHeaderButtonAction,
|
||||||
|
// fish_block_template::FishBlockCategory, fish_doc::FishDoc, fish_patch::*,
|
||||||
|
// fish_ports::ConnectionType,
|
||||||
|
makepad_draw::*,
|
||||||
|
makepad_widgets::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
import crate::fish_block_editor::*;
|
||||||
|
// import crate::fish_theme::*;
|
||||||
|
// import crate::fish_connection_widget::*;
|
||||||
|
// import crate::fish_selector_widget::*;
|
||||||
|
// import crate::block_connector_button::*;
|
||||||
|
|
||||||
|
FishPatchEditor = {{FishPatchEditor}} {
|
||||||
|
width: Fill,
|
||||||
|
height: Fill,
|
||||||
|
scroll_bars: <ScrollBars> {}
|
||||||
|
BlockTemplateGenerator = <FishBlockEditorGenerator>{};
|
||||||
|
BlockTemplateMeta = <FishBlockEditorMeta>{};
|
||||||
|
BlockTemplateFilter = <FishBlockEditorFilter>{};
|
||||||
|
BlockTemplateEffect = <FishBlockEditorEffect>{};
|
||||||
|
BlockTemplateModulator = <FishBlockEditorModulator>{};
|
||||||
|
BlockTemplateEnvelope = <FishBlockEditorEnvelope>{};
|
||||||
|
BlockTemplateUtility = <FishBlockEditorUtility>{};
|
||||||
|
|
||||||
|
ConnectorTemplate = <FishConnectionWidget>{color: #d0d0a0ff};
|
||||||
|
SelectorTemplate = <FishSelectorWidget>{color: #d0d0a0ff};
|
||||||
|
|
||||||
|
AudioButtonTemplate = <BlockConnectorButton>{flow: Overlay, draw_bg: { bodytop: (CABLE_AUDIO_COLOR);}};
|
||||||
|
ControlButtonTemplate = <BlockConnectorButton>{flow: Overlay, draw_bg: { bodytop: (CABLE_CONTROL_COLOR);}};
|
||||||
|
GateButtonTemplate = <BlockConnectorButton>{flow: Overlay, draw_bg: { bodytop: (CABLE_GATE_COLOR);}};
|
||||||
|
MIDIButtonTemplate = <BlockConnectorButton>{flow: Overlay, draw_bg: { bodytop:(CABLE_MIDI_COLOR);}};
|
||||||
|
|
||||||
|
draw_bg: {
|
||||||
|
fn pixel(self) -> vec4 {
|
||||||
|
|
||||||
|
|
||||||
|
return vec4(0.03,0.03,0.03,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct FishPatchEditor {
|
||||||
|
#[animator]
|
||||||
|
animator: Animator,
|
||||||
|
#[walk]
|
||||||
|
walk: Walk,
|
||||||
|
#[live]
|
||||||
|
draw_ls: DrawLine,
|
||||||
|
|
||||||
|
#[redraw]
|
||||||
|
#[live]
|
||||||
|
scroll_bars: ScrollBars,
|
||||||
|
#[live]
|
||||||
|
draw_bg: DrawColor,
|
||||||
|
#[rust]
|
||||||
|
unscrolled_rect: Rect,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
templates: ComponentMap<LiveId, LivePtr>,
|
||||||
|
#[rust]
|
||||||
|
items: ComponentMap<LiveId, (LiveId, WidgetRef)>,
|
||||||
|
#[rust]
|
||||||
|
selectstart: DVec2,
|
||||||
|
#[rust]
|
||||||
|
selectend: DVec2,
|
||||||
|
#[rust]
|
||||||
|
selecting: bool,
|
||||||
|
#[rust]
|
||||||
|
dragstartx: f64,
|
||||||
|
#[rust]
|
||||||
|
dragstarty: f64,
|
||||||
|
#[rust]
|
||||||
|
active_undo_level: usize,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
connectingid: u64,
|
||||||
|
#[rust]
|
||||||
|
connectingx: f64,
|
||||||
|
#[rust]
|
||||||
|
connectingy: f64,
|
||||||
|
#[rust]
|
||||||
|
connectingcurrentx: f64,
|
||||||
|
#[rust]
|
||||||
|
connectingcurrenty: f64,
|
||||||
|
#[rust]
|
||||||
|
connectinginput: bool,
|
||||||
|
#[rust]
|
||||||
|
connecting: bool,
|
||||||
|
|
||||||
|
#[rust]
|
||||||
|
selection: FishPatchSelection,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for FishPatchEditor {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
let uid = self.widget_uid();
|
||||||
|
self.animator_handle_event(cx, event);
|
||||||
|
self.scroll_bars.handle_event(cx, event);
|
||||||
|
|
||||||
|
for (_item_id, item) in self.items.values_mut() {
|
||||||
|
let _item_uid = item.widget_uid();
|
||||||
|
|
||||||
|
for action in cx.capture_actions(|cx| item.handle_event(cx, event, scope)) {
|
||||||
|
match action.as_widget_action().cast() {
|
||||||
|
BlockHeaderButtonAction::Select { id } => {
|
||||||
|
self.selection.clear();
|
||||||
|
self.selection.add(id);
|
||||||
|
}
|
||||||
|
BlockHeaderButtonAction::Move { id, dx, dy } => {
|
||||||
|
self.scroll_bars.redraw(cx);
|
||||||
|
let patch = &mut scope.data.get_mut::<FishDoc>().unwrap().patches[0];
|
||||||
|
patch.move_selection(&self.selection, dx, dy);
|
||||||
|
}
|
||||||
|
BlockHeaderButtonAction::RecordDragStart { id } => {
|
||||||
|
let patch = &mut scope.data.get_mut::<FishDoc>().unwrap().patches[0];
|
||||||
|
let block = patch.blocks.find(id);
|
||||||
|
|
||||||
|
if block.is_some() {
|
||||||
|
if !self.selection.blocks.contains(&id) {
|
||||||
|
if self.selection.blocks.len() > 0 {
|
||||||
|
self.selection.clear();
|
||||||
|
}
|
||||||
|
self.selection.add(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let b = block.unwrap();
|
||||||
|
self.dragstartx = b.x;
|
||||||
|
self.dragstarty = b.y;
|
||||||
|
self.scroll_bars.redraw(cx);
|
||||||
|
self.active_undo_level = patch.undo_checkpoint_start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlockHeaderButtonAction::RecordDragEnd { id: _ } => {
|
||||||
|
let patch = &mut scope.data.get_mut::<FishDoc>().unwrap().patches[0];
|
||||||
|
|
||||||
|
patch.undo_checkpoint_end_if_match(self.active_undo_level);
|
||||||
|
self.active_undo_level = 0;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
match action.as_widget_action().cast() {
|
||||||
|
BlockDeleteButtonAction::KillBlock { id } => {
|
||||||
|
let patch = &mut scope.data.get_mut::<FishDoc>().unwrap().patches[0];
|
||||||
|
patch.remove_block(id);
|
||||||
|
self.scroll_bars.redraw(cx);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match event.hits(cx, self.draw_bg.area()) {
|
||||||
|
Hit::FingerDown(fe) => {
|
||||||
|
// if fe.digit_id == live_id!(0).into() {
|
||||||
|
self.selecting = true;
|
||||||
|
let patch = &mut scope.data.get_mut::<FishDoc>().unwrap().patches[0];
|
||||||
|
|
||||||
|
// start selecting
|
||||||
|
self.selectstart = fe.abs.clone();
|
||||||
|
self.selectend = fe.abs.clone();
|
||||||
|
self.selection = patch.select_rectangle(self.selectstart, self.selectend);
|
||||||
|
// }
|
||||||
|
self.scroll_bars.redraw(cx);
|
||||||
|
self.animator_play(cx, id!(hover.pressed));
|
||||||
|
}
|
||||||
|
|
||||||
|
Hit::FingerMove(fe) => {
|
||||||
|
if
|
||||||
|
//fe.digit_id == live_id!(0).into() &&
|
||||||
|
self.selecting {
|
||||||
|
self.selectend = fe.abs.clone();
|
||||||
|
let patch = &mut scope.data.get_mut::<FishDoc>().unwrap().patches[0];
|
||||||
|
self.selection = patch.select_rectangle(self.selectstart, self.selectend);
|
||||||
|
self.scroll_bars.redraw(cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.digit_id == live_id!(0).into() &&
|
||||||
|
self.selecting {
|
||||||
|
self.selecting = false;
|
||||||
|
// stop selecting
|
||||||
|
self.scroll_bars.redraw(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if fe.is_over {
|
||||||
|
// cx.widget_action(uid, &scope.path, ButtonAction::Clicked);
|
||||||
|
// cx.widget_action(uid, &scope.path, ButtonAction::Released);
|
||||||
|
if fe.device.has_hovers() {
|
||||||
|
self.animator_play(cx, id!(hover.on));
|
||||||
|
} else {
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// cx.widget_action(uid, &scope.path, ButtonAction::Released);
|
||||||
|
self.animator_play(cx, id!(hover.off));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
let patch = &mut scope.data.get_mut::<FishDoc>().unwrap().patches[0];
|
||||||
|
//let mut _fullrect = cx.walk_turtle_with_area(&mut self.area, walk);
|
||||||
|
|
||||||
|
self.scroll_bars.begin(cx, walk, Layout::flow_overlay());
|
||||||
|
|
||||||
|
let _turtle_rect = cx.turtle().rect();
|
||||||
|
let scroll_pos = self.scroll_bars.get_scroll_pos();
|
||||||
|
self.unscrolled_rect = cx.turtle().unscrolled_rect();
|
||||||
|
self.draw_bg.draw_abs(cx, cx.turtle().unscrolled_rect());
|
||||||
|
|
||||||
|
self.draw_connections(cx, patch, scroll_pos);
|
||||||
|
self.draw_selection(cx, patch, scroll_pos);
|
||||||
|
|
||||||
|
for i in &mut patch.blocks.iter_mut() {
|
||||||
|
let item_id = LiveId::from_num(1, i.id as u64);
|
||||||
|
let templateid = match i.category {
|
||||||
|
FishBlockCategory::Effect => live_id!(BlockTemplateEffect),
|
||||||
|
FishBlockCategory::Generator => live_id!(BlockTemplateGenerator),
|
||||||
|
FishBlockCategory::Modulator => live_id!(BlockTemplateModulator),
|
||||||
|
FishBlockCategory::Envelope => live_id!(BlockTemplateEnvelope),
|
||||||
|
FishBlockCategory::Filter => live_id!(BlockTemplateFilter),
|
||||||
|
FishBlockCategory::Meta => live_id!(BlockTemplateMeta),
|
||||||
|
FishBlockCategory::Utility => live_id!(BlockTemplateUtility),
|
||||||
|
};
|
||||||
|
|
||||||
|
let item = self.item(cx, item_id, templateid).unwrap().as_view();
|
||||||
|
|
||||||
|
item.apply_over(
|
||||||
|
cx,
|
||||||
|
live! {title= {topbar = {header= {text: (i.name) , blockid: (i.id)}, delete = {blockid: (i.id)}}},
|
||||||
|
abs_pos: (dvec2(i.x as f64, i.y as f64 )-scroll_pos)},
|
||||||
|
);
|
||||||
|
|
||||||
|
item.draw_all(cx, &mut Scope::empty());
|
||||||
|
let itemarea = item.area().rect(cx);
|
||||||
|
i.h = itemarea.size.y;
|
||||||
|
i.w = itemarea.size.x;
|
||||||
|
|
||||||
|
if self.selection.blocks.contains(&i.id) {
|
||||||
|
self.draw_selected_outline(cx, i.x, i.y, i.w, i.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
for inp in &i.input_ports {
|
||||||
|
let item_id = LiveId::from_num(2000 + i.id, inp.id as u64);
|
||||||
|
let templateid = match inp.datatype {
|
||||||
|
ConnectionType::Audio => live_id!(AudioButtonTemplate),
|
||||||
|
ConnectionType::MIDI => live_id!(MIDIButtonTemplate),
|
||||||
|
ConnectionType::Control => live_id!(ControlButtonTemplate),
|
||||||
|
ConnectionType::Gate => live_id!(GateButtonTemplate),
|
||||||
|
_ => live_id!(AudioButtonTemplate),
|
||||||
|
};
|
||||||
|
let item = self.item(cx, item_id, templateid).unwrap();
|
||||||
|
item.apply_over(
|
||||||
|
cx,
|
||||||
|
live! {
|
||||||
|
input: true,
|
||||||
|
|
||||||
|
abs_pos: (dvec2(i.x as f64, i.y as f64 + inp.id as f64 * 20.)-scroll_pos) ,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
item.draw_all(cx, &mut Scope::empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
for outp in &i.output_ports {
|
||||||
|
let item_id = LiveId::from_num(3000 + i.id, outp.id as u64);
|
||||||
|
let templateid = match outp.datatype {
|
||||||
|
ConnectionType::Audio => live_id!(AudioButtonTemplate),
|
||||||
|
ConnectionType::MIDI => live_id!(MIDIButtonTemplate),
|
||||||
|
ConnectionType::Control => live_id!(ControlButtonTemplate),
|
||||||
|
ConnectionType::Gate => live_id!(GateButtonTemplate),
|
||||||
|
_ => live_id!(AudioButtonTemplate),
|
||||||
|
};
|
||||||
|
let item = self.item(cx, item_id, templateid).unwrap();
|
||||||
|
item.apply_over(
|
||||||
|
cx,
|
||||||
|
live! {
|
||||||
|
input: false,
|
||||||
|
abs_pos: (dvec2(i.x as f64 + itemarea.size.x - 20. + 1., i.y as f64 + outp.id as f64 * 20.)-scroll_pos) ,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
item.draw_all(cx, &mut Scope::empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.connecting {
|
||||||
|
self.draw_active_connection(cx, patch, scroll_pos);
|
||||||
|
}
|
||||||
|
self.scroll_bars.end(cx);
|
||||||
|
|
||||||
|
DrawStep::done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LiveHook for FishPatchEditor {
|
||||||
|
fn after_new_from_doc(&mut self, _cx: &mut Cx) {}
|
||||||
|
|
||||||
|
fn before_apply(
|
||||||
|
&mut self,
|
||||||
|
_cx: &mut Cx,
|
||||||
|
apply: &mut Apply,
|
||||||
|
_index: usize,
|
||||||
|
_nodes: &[LiveNode],
|
||||||
|
) {
|
||||||
|
if let ApplyFrom::UpdateFromDoc { .. } = apply.from {
|
||||||
|
self.templates.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hook the apply flow to collect our templates and apply to instanced childnodes
|
||||||
|
fn apply_value_instance(
|
||||||
|
&mut self,
|
||||||
|
cx: &mut Cx,
|
||||||
|
apply: &mut Apply,
|
||||||
|
index: usize,
|
||||||
|
nodes: &[LiveNode],
|
||||||
|
) -> usize {
|
||||||
|
let id = nodes[index].id;
|
||||||
|
match apply.from {
|
||||||
|
ApplyFrom::NewFromDoc { file_id } | ApplyFrom::UpdateFromDoc { file_id } => {
|
||||||
|
if nodes[index].origin.has_prop_type(LivePropType::Instance) {
|
||||||
|
let live_ptr = cx
|
||||||
|
.live_registry
|
||||||
|
.borrow()
|
||||||
|
.file_id_index_to_live_ptr(file_id, index);
|
||||||
|
self.templates.insert(id, live_ptr);
|
||||||
|
// lets apply this thing over all our childnodes with that template
|
||||||
|
for (templ_id, node) in self.items.values_mut() {
|
||||||
|
if *templ_id == id {
|
||||||
|
node.apply(cx, apply, index, nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
nodes.skip_node(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FishPatchEditor {
|
||||||
|
pub fn item(&mut self, cx: &mut Cx, id: LiveId, template: LiveId) -> Option<WidgetRef> {
|
||||||
|
if let Some(ptr) = self.templates.get(&template) {
|
||||||
|
let (_, entry) = self.items.get_or_insert(cx, id, |cx| {
|
||||||
|
(template, WidgetRef::new_from_ptr(cx, Some(*ptr)))
|
||||||
|
});
|
||||||
|
return Some(entry.clone());
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FishPatchEditor {
|
||||||
|
pub fn draw_active_connection(&mut self, cx: &mut Cx2d, _patch: &FishPatch, scroll_pos: DVec2) {
|
||||||
|
let item_id = LiveId::from_str("ActiveConnectionWidget");
|
||||||
|
|
||||||
|
let templateid = live_id!(ConnectorTemplate);
|
||||||
|
let preitem = self.item(cx, item_id, templateid);
|
||||||
|
let item = preitem.unwrap();
|
||||||
|
if self.connectinginput {
|
||||||
|
item.apply_over(
|
||||||
|
cx,
|
||||||
|
live! {
|
||||||
|
end_pos: (dvec2(self.connectingx as f64 , self.connectingy as f64 ) - scroll_pos),
|
||||||
|
start_pos: (dvec2(self.connectingcurrentx as f64, self.connectingcurrenty as f64) - scroll_pos ),
|
||||||
|
color: #ff0,
|
||||||
|
abs_pos: (dvec2(0.,0.)),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
item.apply_over(
|
||||||
|
cx,
|
||||||
|
live! {
|
||||||
|
start_pos: (dvec2(self.connectingx as f64 , self.connectingy as f64 ) - scroll_pos),
|
||||||
|
end_pos: (dvec2(self.connectingcurrentx as f64, self.connectingcurrenty as f64) - scroll_pos ),
|
||||||
|
color: #ff0,
|
||||||
|
abs_pos: (dvec2(0.,0.)),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
item.draw_all(cx, &mut Scope::empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_selection(&mut self, cx: &mut Cx2d, _patch: &FishPatch, scroll_pos: DVec2) {
|
||||||
|
if self.selecting {
|
||||||
|
let item_id = LiveId::from_str("ActiveSelectionWidget");
|
||||||
|
let templateid = live_id!(SelectorTemplate);
|
||||||
|
let preitem = self.item(cx, item_id, templateid);
|
||||||
|
let item = preitem.unwrap();
|
||||||
|
item.apply_over(
|
||||||
|
cx,
|
||||||
|
live! {
|
||||||
|
start_pos: (self.selectstart - scroll_pos),
|
||||||
|
end_pos: (self.selectend - scroll_pos),
|
||||||
|
color: #eee,
|
||||||
|
line_width: 2.0
|
||||||
|
},
|
||||||
|
);
|
||||||
|
item.draw_all(cx, &mut Scope::empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_selected_outline(&mut self, cx: &mut Cx2d, x: f64, y: f64, w: f64, h: f64) {
|
||||||
|
let tl = DVec2 {
|
||||||
|
x: x as f64 - 1.5,
|
||||||
|
y: y as f64 - 1.5,
|
||||||
|
};
|
||||||
|
let br = DVec2 {
|
||||||
|
x: (x + w) as f64 + 1.5,
|
||||||
|
y: (y + h) as f64 + 1.5,
|
||||||
|
};
|
||||||
|
|
||||||
|
let bl = DVec2 { x: tl.x, y: br.y };
|
||||||
|
let tr = DVec2 { x: br.x, y: tl.y };
|
||||||
|
let color = vec4(1., 1., 0., 1.);
|
||||||
|
self.draw_ls.draw_line_abs(cx, tl, tr, color, 4.);
|
||||||
|
self.draw_ls.draw_line_abs(cx, tr, br, color, 4.);
|
||||||
|
self.draw_ls.draw_line_abs(cx, br, bl, color, 4.);
|
||||||
|
self.draw_ls.draw_line_abs(cx, tl, bl, color, 4.);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw_connections(&mut self, cx: &mut Cx2d, patch: &FishPatch, scroll_pos: DVec2) {
|
||||||
|
for i in patch.connections.iter() {
|
||||||
|
let item_id = LiveId::from_num(2, i.id as u64);
|
||||||
|
|
||||||
|
let templateid = live_id!(ConnectorTemplate);
|
||||||
|
let preitem = self.item(cx, item_id, templateid);
|
||||||
|
let item = preitem.unwrap();
|
||||||
|
|
||||||
|
let blockfromopt = patch.get_block(&i.from_block);
|
||||||
|
let blocktoopt = patch.get_block(&i.to_block);
|
||||||
|
let mut inselection = false;
|
||||||
|
|
||||||
|
if blockfromopt.is_some() && blocktoopt.is_some() {
|
||||||
|
let blockfrom = blockfromopt.unwrap();
|
||||||
|
let blockto = blocktoopt.unwrap();
|
||||||
|
let _portfrom = blockfrom.get_output_instance(i.from_port).unwrap();
|
||||||
|
let _portto = blockto.get_input_instance(i.to_port).unwrap();
|
||||||
|
|
||||||
|
if self.selection.blocks.contains(&blockfrom.id)
|
||||||
|
&& self.selection.blocks.contains(&blockto.id)
|
||||||
|
{
|
||||||
|
inselection = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
item.apply_over( cx, live! {
|
||||||
|
start_pos: (dvec2(blockfrom.x as f64 + 200.0, blockfrom.y as f64 + 10. + 20. * _portfrom.id as f64) - scroll_pos),
|
||||||
|
end_pos: (dvec2(blockto.x as f64, blockto.y as f64+ 10. + 20. * _portto.id as f64) - scroll_pos ),
|
||||||
|
from_top: (blockfrom.y- scroll_pos.y ),
|
||||||
|
from_bottom: (blockfrom.y + blockfrom.h - scroll_pos.y ),
|
||||||
|
to_top: (blockto.y - scroll_pos.y ),
|
||||||
|
to_bottom: (blockto.y + blockto.h - scroll_pos.y ) ,
|
||||||
|
color: #x888,
|
||||||
|
abs_pos: (dvec2(0.,0.)),
|
||||||
|
selected: (inselection)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
item.draw_all(cx, &mut Scope::empty());
|
||||||
|
}
|
||||||
|
// println!("{:?} ({:?},{:?})", i.id, i.x,i.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
src/shared/editor/mod.rs
Normal file
2
src/shared/editor/mod.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod fish_block_editor;
|
||||||
|
pub mod fish_patch_editor;
|
|
@ -1,5 +1,6 @@
|
||||||
use makepad_widgets::Cx;
|
use makepad_widgets::Cx;
|
||||||
|
|
||||||
|
// pub mod editor;
|
||||||
pub mod styles;
|
pub mod styles;
|
||||||
pub mod widgets;
|
pub mod widgets;
|
||||||
|
|
||||||
|
@ -7,6 +8,7 @@ pub fn live_design(cx: &mut Cx) {
|
||||||
styles::live_design(cx);
|
styles::live_design(cx);
|
||||||
// resource_imports::live_design(cx);
|
// resource_imports::live_design(cx);
|
||||||
widgets::live_design(cx);
|
widgets::live_design(cx);
|
||||||
|
// editor::live_design(cx);
|
||||||
// portal::live_design(cx);
|
// portal::live_design(cx);
|
||||||
// modal::live_design(cx);
|
// modal::live_design(cx);
|
||||||
// external_link::live_design(cx);
|
// external_link::live_design(cx);
|
||||||
|
|
128
src/web.rs
Normal file
128
src/web.rs
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
use makepad_widgets::*;
|
||||||
|
|
||||||
|
live_design! {
|
||||||
|
import makepad_widgets::base::*;
|
||||||
|
import makepad_widgets::theme_desktop_dark::*;
|
||||||
|
|
||||||
|
import crate::shared::styles::*;
|
||||||
|
import crate::home::home_screen::HomeScreen;
|
||||||
|
import crate::aboutus::about_us::AboutUs;
|
||||||
|
|
||||||
|
import crate::shared::widgets::NavbarMenuButton;
|
||||||
|
|
||||||
|
ICON_DISCOVER = dep("crate://self/resources/icons/discover.svg")
|
||||||
|
ICON_CHAT = dep("crate://self/resources/icons/chat.svg")
|
||||||
|
ICON_MY_MODELS = dep("crate://self/resources/icons/my_models.svg")
|
||||||
|
|
||||||
|
AppWebUI = <ScrollXYView>{
|
||||||
|
width: Fill,
|
||||||
|
height: Fill,
|
||||||
|
align: {x: 0.5},
|
||||||
|
padding: {top: 0, bottom: 48 }
|
||||||
|
// debug: A
|
||||||
|
|
||||||
|
navbar_menu = <RoundedView> {
|
||||||
|
width: Fill,
|
||||||
|
height: Fit,
|
||||||
|
flow: Right, spacing: 20.0,
|
||||||
|
padding: { top: 0 }
|
||||||
|
align: {x: 0.5, y: 0.0},
|
||||||
|
|
||||||
|
show_bg: true,
|
||||||
|
draw_bg: {
|
||||||
|
color: (SIDEBAR_BG_COLOR),
|
||||||
|
instance radius: 0.0,
|
||||||
|
border_color: #EAECF0,
|
||||||
|
border_width: 1.2,
|
||||||
|
}
|
||||||
|
home_screen_tab = <NavbarMenuButton> {
|
||||||
|
animator: {selected = {default: on}}
|
||||||
|
text: "Home",
|
||||||
|
draw_icon: {
|
||||||
|
svg_file: (ICON_DISCOVER),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aboutus_screen_tab = <NavbarMenuButton> {
|
||||||
|
text: "About Us",
|
||||||
|
draw_icon: {
|
||||||
|
svg_file: (ICON_MY_MODELS),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
application_pages = <View> {
|
||||||
|
margin: 0.0,
|
||||||
|
padding: 0.0,
|
||||||
|
flow: Down,
|
||||||
|
width: Fill,
|
||||||
|
height: Fill,
|
||||||
|
// debug: A
|
||||||
|
|
||||||
|
home_screen_frame = <HomeScreen> {visible: true}
|
||||||
|
aboutus_screen_frame = <AboutUs> {visible: false}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Live, Widget)]
|
||||||
|
pub struct AppWebUI {
|
||||||
|
#[deref]
|
||||||
|
view: Window,
|
||||||
|
// #[live]
|
||||||
|
// view: WidgetRef,
|
||||||
|
}
|
||||||
|
impl LiveHook for AppWebUI {
|
||||||
|
fn after_new_from_doc(&mut self, _cx: &mut Cx) {
|
||||||
|
println!("after_new_from_doc(): starting some kind of a loop");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Widget for AppWebUI {
|
||||||
|
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
|
||||||
|
self.view.handle_event(cx, event, scope);
|
||||||
|
self.widget_match_event(cx, event, scope);
|
||||||
|
}
|
||||||
|
// fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
|
||||||
|
// self.match_event(cx, event);
|
||||||
|
// self.view.handle_event(cx, event, &mut Scope::empty());
|
||||||
|
// }
|
||||||
|
fn draw_walk(&mut self, cx: &mut Cx2d, scope: &mut Scope, walk: Walk) -> DrawStep {
|
||||||
|
// DrawStep::done()
|
||||||
|
self.view.draw_walk(cx, scope, walk)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WidgetMatchEvent for AppWebUI {
|
||||||
|
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, scope: &mut Scope) {
|
||||||
|
self.view
|
||||||
|
.radio_button_set(ids!(
|
||||||
|
navbar_menu.home_screen_tab,
|
||||||
|
navbar_menu.aboutus_screen_tab,
|
||||||
|
))
|
||||||
|
.selected_to_visible(
|
||||||
|
cx,
|
||||||
|
&self.view,
|
||||||
|
actions,
|
||||||
|
ids!(
|
||||||
|
application_pages.home_screen_frame,
|
||||||
|
application_pages.aboutus_screen_frame,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> src/app_web.rs:102:17
|
||||||
|
|
|
||||||
|
100 | .selected_to_visible(
|
||||||
|
| ------------------- arguments to this method are incorrect
|
||||||
|
101 | cx,
|
||||||
|
102 | &self.view,
|
||||||
|
| ^^^^^^^^^^ expected `&WidgetRef`, found `&Window`
|
||||||
|
|
|
||||||
|
= note: expected reference `&makepad_widgets::WidgetRef`
|
||||||
|
found reference `&makepad_widgets::Window`
|
||||||
|
note: method defined here
|
||||||
|
--> /Users/aok/Projects/rustdev/MadeByMakepad/makepad/widgets/src/radio_button.rs:202:12
|
||||||
|
|
|
||||||
|
202 | pub fn selected_to_visible(&self, cx: &mut Cx, ui:&WidgetRef, actions: &Actions, paths:&[&[Liv...
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^
|
||||||
|
*/
|
Loading…
Add table
Add a link
Reference in a new issue