use crate::{
makepad_derive_widget::*,
makepad_draw::*,
multi_window::*,
widget_match_event::*,
designer_data::*,
designer_view::*,
designer_outline_tree::*,
widget::*,
makepad_platform::studio::*,
};
live_design!{
link designer_real
use link::widgets::*;
use link::theme::*;
use crate::designer_outline::*;
use crate::designer_outline_tree::*;
use crate::designer_toolbox::*;
use crate::designer_view::*;
use crate::designer_theme::*;
DesignerBase = {{Designer}} {
}
pub Designer = <DesignerBase>{
<Window> {
window: { kind_id: 2 }
body = <View> {
designer_outline = <DesignerOutline> {
flow: Down,
<DockToolbar> {
content = {
margin: {left: (THEME_SPACE_1), right: (THEME_SPACE_1) },
align: { x: 0., y: 0.0 }
spacing: (THEME_SPACE_3)
<Pbold> {
width: Fit,
text: "Filter",
margin: 0.,
padding: <THEME_MSPACE_V_1> {}
}
<View> {
width: Fit
flow: Right,
spacing: (THEME_SPACE_1)
<CheckBoxCustom> {
width: 25,
margin: {left: (THEME_SPACE_1)}
text: ""
draw_bg: { check_type: None }
icon_walk: {width: 13.5 }
draw_icon: {
color: (THEME_COLOR_D_3),
color_active: (STUDIO_PALETTE_2),
svg_file: dep("crate://self/resources/icons/icon_widget.svg"),
}
}
<CheckBoxCustom> {
width: 25,
text: ""
draw_bg: { check_type: None }
icon_walk: {width: 12.}
draw_icon: {
color: (THEME_COLOR_D_3),
color_active: (STUDIO_PALETTE_6),
svg_file: dep("crate://self/resources/icons/icon_layout.svg"),
}
}
<CheckBoxCustom> {
width: 25,
text: ""
draw_bg: { check_type: None }
icon_walk: {width: 10.5}
draw_icon: {
color: (THEME_COLOR_D_3),
color_active: (STUDIO_PALETTE_1),
svg_file: dep("crate://self/resources/icons/icon_text.svg"),
}
}
<CheckBoxCustom> {
width: 25,
text:""
draw_bg: { check_type: None }
icon_walk: {width: 13.}
draw_icon: {
color: (THEME_COLOR_D_3),
color_active: (STUDIO_PALETTE_5),
svg_file: dep("crate://self/resources/icons/icon_image.svg"),
}
}
}
<TextInputFlat> {
width: Fill,
empty_text: "Filter",
}
}
}
outline_tree = <DesignerOutlineTree>{
}
}
}
}
<Window>{
window:{ kind_id: 1 }
body = <View>{
flow: Overlay
designer_view = <DesignerView> {
width: Fill, height: Fill
}
toolbox = <DesignerToolbox>{
}
}
}
}
}
#[derive(Live, Widget)]
pub struct Designer {
#[deref] ui: MultiWindow,
#[rust] data: DesignerData,
}
impl LiveHook for Designer {
fn before_apply(&mut self, cx: &mut Cx, _apply: &mut Apply, _index: usize, _nodes: &[LiveNode]){
self.data.update_from_live_registry(cx);
}
fn after_update_from_doc(&mut self, cx:&mut Cx){
let outline_tree = self.ui.designer_outline_tree(id!(outline_tree));
outline_tree.redraw(cx);
self.data.pending_revision = false;
}
fn after_new_from_doc(&mut self, _cx:&mut Cx){
Cx::send_studio_message(AppToStudio::DesignerStarted);
}
}
impl Designer{
fn studio_jump_to_component(&self, cx:&Cx, component:LiveId){
if let Some(OutlineNode::Component{ptr,..}) = self.data.node_map.get(&component){
let (file_name,span) = cx.live_registry.borrow().ptr_to_file_name_and_object_span(*ptr);
Cx::send_studio_message(AppToStudio::JumpToFile(JumpToFile{
file_name,
line: span.start.line,
column: span.start.column
}));
}
}
fn studio_select_component(&self, cx:&Cx, component:LiveId){
if let Some(OutlineNode::Component{ptr,..}) = self.data.node_map.get(&component){
let (file_name,span) = cx.live_registry.borrow().ptr_to_file_name_and_object_span(*ptr);
println!("{:?}", span);
Cx::send_studio_message(AppToStudio::SelectInFile(SelectInFile{
file_name,
line_start: span.start.line,
column_start: span.start.column,
line_end: span.end.line,
column_end: span.end.column
}));
}
}
fn studio_swap_components(&mut self, cx:&Cx, c1:LiveId, c2:LiveId){
if self.data.pending_revision{
return
}
if let Some(OutlineNode::Component{ptr:ptr1,..}) = self.data.node_map.get(&c1){
if let Some(OutlineNode::Component{ptr:ptr2,..}) = self.data.node_map.get(&c2){
let (s1_file_name,s1_span) = cx.live_registry.borrow().ptr_to_file_name_and_object_span(*ptr1);
let (s2_file_name,s2_span) = cx.live_registry.borrow().ptr_to_file_name_and_object_span(*ptr2);
self.data.pending_revision = true;
Cx::send_studio_message(AppToStudio::SwapSelection(SwapSelection{
s1_file_name,
s1_line_start: s1_span.start.line,
s1_column_start: s1_span.start.column,
s1_line_end: s1_span.end.line,
s1_column_end: s1_span.end.column,
s2_file_name,
s2_line_start: s2_span.start.line,
s2_column_start: s2_span.start.column,
s2_line_end: s2_span.end.line,
s2_column_end: s2_span.end.column,
}));
}
}
}
fn studio_jump_to_file(&self, cx:&Cx, file_id:LiveFileId){
let file_name = cx.live_registry.borrow().file_id_to_file(file_id).file_name.clone();
Cx::send_studio_message(AppToStudio::JumpToFile(JumpToFile{
file_name,
line: 0,
column: 0
}));
}
}
impl WidgetMatchEvent for Designer{
fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions, _scope: &mut Scope){
let outline_tree = self.ui.designer_outline_tree(id!(outline_tree));
let designer_view = self.ui.designer_view(id!(designer_view));
if let Some((outline_id, km, tap_count)) = designer_view.selected(&actions){
let path_ids = self.data.construct_path_ids(outline_id);
outline_tree.select_and_show_node(cx, &path_ids);
if km.control || tap_count > 1{
self.studio_select_component(cx, outline_id)
}
}
if let Some((c1, c2)) = designer_view.swap_components(&actions){
self.studio_swap_components(cx, c1, c2);
outline_tree.redraw(cx);
}
for action in actions{
if let StudioToApp::DesignerSelectFile{file_name} = action.cast_ref(){
let path_ids = DesignerData::path_str_to_path_ids(&file_name);
if path_ids.len() > 0{
outline_tree.select_and_show_node(cx, &path_ids);
designer_view.select_component(cx, None);
designer_view.view_file(cx, *path_ids.last().unwrap());
}
}
if let StudioToApp::DesignerLoadState{positions, zoom_pan} = action.cast_ref(){
self.data.to_widget.positions = positions.clone();
designer_view.set_zoom_pan(cx,zoom_pan);
}
}
if let Some((outline_id,km)) = outline_tree.selected(&actions) {
if let Some(node) = self.data.node_map.get(&outline_id){
match node{
OutlineNode::File{file_id,..}=>{
let path_ids = self.data.construct_path_ids(outline_id);
let file_name = self.data.path_ids_to_string(&path_ids);
Cx::send_studio_message(AppToStudio::DesignerFileSelected{
file_name
});
if km.control{
self.studio_jump_to_file(cx, *file_id);
}
else if km.alt{
Cx::send_studio_message(AppToStudio::FocusDesign);
}
else{
designer_view.select_component(cx, None);
designer_view.view_file(cx, outline_id);
}
}
OutlineNode::Component{..}=>{
if km.control{
self.studio_jump_to_component(cx, outline_id)
}
else if km.alt{
Cx::send_studio_message(AppToStudio::FocusDesign);
}
else{
if let Some(file_id) = self.data.find_file_parent(outline_id){
designer_view.select_component(cx, Some(outline_id));
designer_view.view_file(cx, file_id);
}
}
}
_=>()
}
}
}
}
}
impl Widget for Designer {
fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope){
self.widget_match_event(cx, event, scope);
let mut scope = Scope::with_data(&mut self.data);
self.ui.handle_event(cx, event, &mut scope);
}
fn draw_walk(&mut self, cx: &mut Cx2d, _scope:&mut Scope, _walk: Walk) -> DrawStep {
let mut scope = Scope::with_data(&mut self.data);
self.ui.draw(cx, &mut scope)
}
}