Skip to content

Commit

Permalink
contextual drilling fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelselleck committed Sep 12, 2024
1 parent 2c19fc8 commit 8eb9861
Show file tree
Hide file tree
Showing 14 changed files with 205 additions and 130 deletions.
74 changes: 37 additions & 37 deletions pax-designer/src/controls/settings/mod.pax
Original file line number Diff line number Diff line change
Expand Up @@ -15,50 +15,50 @@ if self.is_component_selected {
}
</Group>

<Text text={self.selected_component_name} class=h1 class=col_1 class=span_6 />
<Group height=150px y=47px>
<Group y=0px height=30px>
<Text text="x" class=property_label class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="x" class=col_2 class=span_3 />
<Text text="y" class=property_label class=col_5 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="y" class=col_6 class=span_3 />
</Group>
<Group y=40px height=30px>
<Text text="w" class=property_label class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="width" class=col_2 class=span_3 />
<Text text="h" class=property_label class=col_5 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="height" class=col_6 class=span_3 />
</Group>
</Group>
<Path class=hr y=135px class=col_1 class=span_6 />
<Group y=145px height=180px>
<Text text="Transform" class=h2 class=col_1 class=span_6 />
<Group y=30px height={100% - 30px}>
<Text text={self.selected_component_name} class=h1 class=col_1 class=span_6 />
<Group height=150px y=47px>
<Group y=0px height=30px>
<Text text="⊾" class=property_label_larger class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="rotate" class=col_2 class=span_3 />
<Text text="x" class=property_label class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="x" class=col_2 class=span_3 />
<Text text="y" class=property_label class=col_5 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="y" class=col_6 class=span_3 />
</Group>
<Group y=40px height=30px>
<Text text="↔x" class=property_label class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="scale_x" class=col_2 class=span_3 />
<Text text="↕y" class=property_label class=col_5 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="scale_y" class=col_6 class=span_3 />
<Text text="w" class=property_label class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="width" class=col_2 class=span_3 />
<Text text="h" class=property_label class=col_5 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="height" class=col_6 class=span_3 />
</Group>
<Group y=80px height=30px>
<Text text="⨁x" class=property_label class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="anchor_x" class=col_2 class=span_3 />
<Text text="⨁y" class=property_label class=col_5 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="anchor_y" class=col_6 class=span_3 />
</Group>
<Group y=120px height=30px>
<Text text="▱x" class=property_label class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="skew_x" class=col_2 class=span_3 />
<Text text="▱y" class=property_label class=col_5 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="skew_y" class=col_6 class=span_3 />
</Group>
<Path class=hr y=135px class=col_1 class=span_6 />
<Group y=145px height=180px>
<Text text="Transform" class=h2 class=col_1 class=span_6 />
<Group y=30px height={100% - 30px}>
<Group y=0px height=30px>
<Text text="⊾" class=property_label_larger class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="rotate" class=col_2 class=span_3 />
</Group>
<Group y=40px height=30px>
<Text text="↔x" class=property_label class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="scale_x" class=col_2 class=span_3 />
<Text text="↕y" class=property_label class=col_5 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="scale_y" class=col_6 class=span_3 />
</Group>
<Group y=80px height=30px>
<Text text="⨁x" class=property_label class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="anchor_x" class=col_2 class=span_3 />
<Text text="⨁y" class=property_label class=col_5 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="anchor_y" class=col_6 class=span_3 />
</Group>
<Group y=120px height=30px>
<Text text="▱x" class=property_label class=col_1 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="skew_x" class=col_2 class=span_3 />
<Text text="▱y" class=property_label class=col_5 class=span_1 />
<PropertyEditor stid={self.stid} snid={self.snid} name="skew_y" class=col_6 class=span_3 />
</Group>
</Group>
</Group>
</Group>
</Group>
</Scroller>
}

Expand Down
69 changes: 44 additions & 25 deletions pax-designer/src/controls/tree/mod.pax
Original file line number Diff line number Diff line change
@@ -1,30 +1,49 @@

<Scroller scroll_height={(Math::len(self.tree_objects)*42 + 42)px}>
for (obj, i) in self.tree_objects {
<TreeObj
ind={obj.ind}
y={(i*36)px}
anchor_x=0%
anchor_y=0%
x={(obj.indent_level*6)%}
is_selected={obj.is_selected}
height=34px
name={obj.name}
is_container={obj.is_container}
width={(100.0 - obj.indent_level*6)%}
image_path={obj.image_path}
uid={obj.node_id}
/>
}
if self.dragging {
<Rectangle
x={(self.drag_indent*6)%}
anchor_x=0%
width={(100 - self.drag_indent*8)%}
y={(34 + self.drag_id*36 - 36*self.drag_top_half)px}
height=2px fill=WHITE
/>
}
<Group>
for (obj, i) in self.tree_objects {
<TreeObj
ind={obj.ind}
y={(i*36)px}
anchor_x=0%
anchor_y=0%
x={(obj.indent_level*6)%}
is_selected={obj.is_selected}
height=34px
name={obj.name}
is_container={obj.is_container}
width={(100.0 - obj.indent_level*6)%}
image_path={obj.image_path}
uid={obj.node_id}
/>
}


if self.dragging {
<Rectangle
x={(self.drag_indent*6)%}
anchor_x=0%
width={(100 - self.drag_indent*8)%}
y={(34 + self.drag_id*36 - 36*self.drag_top_half)px}
height=2px fill=WHITE
_raycastable=false
/>
}
// WARNING: This if statement + invisible rectangle is needed to make double
// clicking in the tree view work. If not present, the EventBlockers in the
// tree objects shift layers between clicks, resulting in double click not being
// fired by the browser.
if !self.dragging {
<Rectangle
x={(self.drag_indent*6)%}
anchor_x=0%
width={(100 - self.drag_indent*8)%}
y={(34 + self.drag_id*36 - 36*self.drag_top_half)px}
height=2px fill=TRANSPARENT
_raycastable=false
/>
}
</Group>
</Scroller>
<Rectangle fill=TRANSPARENT/>

Expand Down
18 changes: 11 additions & 7 deletions pax-designer/src/controls/tree/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use anyhow::Result;
use pax_designtime::orm::PaxManifestORM;
use pax_engine::api::*;
use pax_engine::node_layout::LayoutProperties;
use pax_engine::*;
Expand Down Expand Up @@ -72,10 +73,10 @@ impl TreeEntry {
self,
ind: &mut usize,
indent_level: isize,
ctx: &NodeContext,
orm: &PaxManifestORM,
) -> Vec<FlattenedTreeEntry> {
let mut all = vec![];
let desc = self.node_type.metadata(ctx);
let desc = self.node_type.metadata(orm);
all.push(FlattenedTreeEntry {
node_id: self.node_id,
name: desc.name,
Expand All @@ -90,7 +91,7 @@ impl TreeEntry {
all.extend(
self.children
.into_iter()
.flat_map(|c| c.flatten(ind, indent_level + 1, ctx)),
.flat_map(|c| c.flatten(ind, indent_level + 1, orm)),
);
all
}
Expand Down Expand Up @@ -159,6 +160,9 @@ impl Tree {
builder.get_type_id()
};
model::perform_action(&SetEditingComponent(type_id_of_tree_target), &ctx);
// unfortunately we've triggered drag behavior on the single click. If we don't
// reset this, movement can happen when the new tree is loaded on mouse release
self.dragging.set(false);
}
TreeMsg::ObjMouseDown(sender, x_offset) => {
model::perform_action(
Expand Down Expand Up @@ -279,7 +283,7 @@ impl Tree {

let to_node_container = match to_node
.get_node_type(&ctx.engine_context)
.metadata(&ctx.engine_context)
.metadata(&borrow!(ctx.engine_context.designtime).get_orm())
.is_container
&& !top_half
{
Expand Down Expand Up @@ -342,7 +346,7 @@ impl Tree {
};
let node_layout = if to_node_container
.get_node_type(&ctx.engine_context)
.metadata(&ctx.engine_context)
.metadata(&borrow!(ctx.engine_context.designtime).get_orm())
.is_slot_container
{
NodeLayoutSettings::Fill::<Glass>
Expand Down Expand Up @@ -376,7 +380,7 @@ impl Tree {
}

fn get_tree(type_id: TypeId, ctx: &NodeContext) -> Vec<FlattenedTreeEntry> {
let dt = borrow_mut!(ctx.designtime);
let dt = borrow!(ctx.designtime);
let Ok(comp) = dt.get_orm().get_component(&type_id) else {
pax_engine::log::warn!("couldn't find component for tree view");
return Vec::new();
Expand All @@ -391,7 +395,7 @@ fn get_tree(type_id: TypeId, ctx: &NodeContext) -> Vec<FlattenedTreeEntry> {
.iter()
.flat_map(|tnid| {
let tree = to_tree(tnid, &template);
tree.map(|t| t.flatten(&mut ind, 0, ctx))
tree.map(|t| t.flatten(&mut ind, 0, &dt.get_orm()))
.unwrap_or_default()
})
.collect();
Expand Down
4 changes: 1 addition & 3 deletions pax-designer/src/controls/tree/treeobj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl TreeObj {
})
}

pub fn obj_double_clicked(&mut self, _ctx: &NodeContext, _args: Event<DoubleClick>) {
pub fn obj_double_clicked(&mut self, _ctx: &NodeContext, _event: Event<DoubleClick>) {
super::TREE_CLICK_PROP.with_borrow_mut(|cn| {
cn.push_back(super::TreeMsg::ObjDoubleClicked(
self.ind.get().clone().into(),
Expand All @@ -70,7 +70,6 @@ impl TreeObj {
}

pub fn mouse_down(&mut self, _ctx: &NodeContext, event: Event<MouseDown>) {
event.prevent_default();
super::TREE_CLICK_PROP.with_borrow_mut(|cn| {
cn.push_back(super::TreeMsg::ObjMouseDown(
self.ind.get().clone().into(),
Expand All @@ -80,7 +79,6 @@ impl TreeObj {
}

pub fn mouse_move(&mut self, ctx: &NodeContext, event: Event<MouseMove>) {
event.prevent_default();
let local = ctx.local_point(Point2::new(event.mouse.x, event.mouse.y));
let top_half = local.y < 0.5;
super::TREE_CLICK_PROP.with_borrow_mut(|cn| {
Expand Down
32 changes: 18 additions & 14 deletions pax-designer/src/designer_node_type.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use pax_designtime::{orm::PaxManifestORM, DesigntimeManager};
use pax_engine::{
api::{borrow, NodeContext},
pax_manifest::{PaxType, TypeId},
Expand Down Expand Up @@ -26,7 +27,8 @@ pub enum DesignerNodeType {
RadioSet,
If,
For,
Unregistered(String),
Slot,
Unregistered,
Carousel,
}

Expand All @@ -47,9 +49,10 @@ impl DesignerNodeType {
match type_id.get_pax_type() {
PaxType::If => DesignerNodeType::If,
PaxType::Repeat => DesignerNodeType::For,
PaxType::Slot => DesignerNodeType::Slot,
_ => {
let Some(import_path) = type_id.import_path() else {
return DesignerNodeType::Unregistered(type_id.get_unique_identifier());
return DesignerNodeType::Unregistered;
};
// TODO make this and the metadata method use the same constants, or maybe even a signle
// Vec<(TypeId, DesignerNodeType)> that can be searched in either direction.
Expand Down Expand Up @@ -82,7 +85,7 @@ impl DesignerNodeType {
}
}

pub fn metadata(&self, _ctx: &NodeContext) -> DesignerNodeTypeData {
pub fn metadata(&self, orm: &PaxManifestORM) -> DesignerNodeTypeData {
let (name, img_path_suffix, type_id, is_container) = match self {
DesignerNodeType::Frame => (
"Frame",
Expand Down Expand Up @@ -141,9 +144,8 @@ impl DesignerNodeType {
DesignerNodeType::Component { name, import_path } => {
let type_id = TypeId::build_singleton(import_path, None);
// TODO make this dynamic
// let dt = borrow!(ctx.designtime);
// let has_slots = dt.get_orm().component_has_slots(type_id);
(name.as_str(), "component", type_id, true)
let has_slots = orm.component_has_slots(&type_id);
(name.as_str(), "component", type_id, has_slots)
}
DesignerNodeType::Textbox => (
"Textbox",
Expand Down Expand Up @@ -189,24 +191,26 @@ impl DesignerNodeType {
),
DesignerNodeType::If => ("If", "if", TypeId::build_if(), true),
DesignerNodeType::For => ("For", "for", TypeId::build_repeat(), true),
DesignerNodeType::Unregistered(ident) => (
"[Unregistered Type]",
"component",
TypeId::build_singleton(ident, None),
false,
),
DesignerNodeType::Unregistered => {
("[Unregistered Type]", "component", TypeId::default(), false)
}
// TODO add custom image
DesignerNodeType::RadioSet => (
"Radio Set",
"component",
TypeId::build_singleton("pax_std::forms::radio_set::RadioSet", None),
false,
),
DesignerNodeType::Slot => (
"Slot",
"component", // TODO custom image
TypeId::build_slot(),
false,
),
};

// move to match statement above if more types need this specified
let is_slot_container =
self == &DesignerNodeType::Stacker || self == &DesignerNodeType::Carousel;
let is_slot_container = self != &DesignerNodeType::Scroller;

DesignerNodeTypeData {
name: name.to_owned(),
Expand Down
35 changes: 27 additions & 8 deletions pax-designer/src/glass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ impl Glass {
});
if let Some((node_id, uid)) = info {
let designer_node = DesignerNodeType::from_type_id(node_id);
let metadata = designer_node.metadata(ctx);
let metadata = designer_node.metadata(&borrow!(ctx.designtime).get_orm());

match designer_node {
_ if metadata.is_container => {
model::with_action_context(ctx, |ac| {
Expand All @@ -220,14 +221,32 @@ impl Glass {
&[],
);
if let Some(hit) = hit {
if let Err(e) = (SelectNodes {
ids: &[hit.global_id().unwrap().get_template_node_id()],
mode: model::tools::SelectMode::Dynamic,
}
.perform(ac))
if let Some(hit_type) = hit
.global_id()
.map(|id| id.get_containing_component_type_id())
{
log::warn!("failed to drill into container: {}", e);
};
// If the type id of the node hit during the drill hit is different than the current
// component, go into that component. If it's the same, this was a slot component
// and we want to drill into it.
if hit_type != ac.app_state.selected_component_id.get() {
if let Err(e) =
SetEditingComponent(metadata.type_id).perform(ac)
{
log::warn!("failed to set editing component: {}", e);
}
} else {
if let Err(e) = (SelectNodes {
ids: &[hit.global_id().unwrap().get_template_node_id()],
mode: model::tools::SelectMode::Dynamic,
}
.perform(ac))
{
log::warn!("failed to drill into container: {}", e);
};
}
} else {
log::warn!("drill node had no type id");
}
}
});
}
Expand Down
Loading

0 comments on commit 8eb9861

Please sign in to comment.