Commit a6dcc1ab authored by Diego Barreiro's avatar Diego Barreiro Committed by Susan Rati Lane

feat(ui): Allow filtering components in source structure

Introduces a dropdown which allows to select if the source structure box should display all components, only the visible ones or the non visible ones.

Change-Id: I1121c78c82a9eddab1abc696d5af865460fcad50
parent 17b754f9
...@@ -920,6 +920,18 @@ public interface OdeMessages extends Messages, AutogeneratedOdeMessages { ...@@ -920,6 +920,18 @@ public interface OdeMessages extends Messages, AutogeneratedOdeMessages {
@Description("Caption for source structure box.") @Description("Caption for source structure box.")
String sourceStructureBoxCaption(); String sourceStructureBoxCaption();
@DefaultMessage("All Components")
@Description("Caption for source structure box.")
String sourceStructureBoxCaptionAll();
@DefaultMessage("Visible Components")
@Description("Caption for source structure box.")
String sourceStructureBoxCaptionVisible();
@DefaultMessage("Non-visible Components")
@Description("Caption for source structure box.")
String sourceStructureBoxCaptionNonVisible();
// Used in BlocksToolkit (SubsetJSONPropertyEditor) // Used in BlocksToolkit (SubsetJSONPropertyEditor)
@DefaultMessage("Blocks Toolkit") @DefaultMessage("Blocks Toolkit")
......
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.client.boxes;
import com.google.appinventor.client.editor.simple.components.MockForm;
import com.google.appinventor.client.editor.youngandroid.YaFormEditor;
import com.google.appinventor.client.explorer.SourceStructureExplorer;
public interface ISourceStructureBox {
/**
* Method to retrieve the rendered source structure explorer from the "child" boxes.
* @return SourceStructureExplorer
*/
SourceStructureExplorer getSourceStructureExplorer();
/**
* Method render the "child" boxes.
*/
void show(MockForm form);
}
// -*- mode: java; c-basic-offset: 2; -*- // -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved // Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved // Copyright 2011-2023 MIT, All rights reserved
// Released under the Apache License, Version 2.0 // Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0 // http://www.apache.org/licenses/LICENSE-2.0
...@@ -9,20 +9,19 @@ package com.google.appinventor.client.boxes; ...@@ -9,20 +9,19 @@ package com.google.appinventor.client.boxes;
import static com.google.appinventor.client.Ode.MESSAGES; import static com.google.appinventor.client.Ode.MESSAGES;
import com.google.appinventor.client.editor.simple.components.MockForm; import com.google.appinventor.client.editor.simple.components.MockForm;
import com.google.appinventor.client.editor.youngandroid.YaFormEditor;
import com.google.appinventor.client.explorer.SourceStructureExplorer; import com.google.appinventor.client.explorer.SourceStructureExplorer;
import com.google.appinventor.client.widgets.boxes.Box; import com.google.appinventor.client.widgets.boxes.Box;
import com.google.appinventor.common.version.AppInventorFeatures;
import com.google.gwt.user.client.ui.DockPanel;
/** /**
* Box implementation for source structure explorer. * Box implementation for source structure explorer.
*
*/ */
public final class SourceStructureBox extends Box { public class SourceStructureBox extends Box implements ISourceStructureBox {
// Singleton source structure explorer box instance // Singleton source structure explorer box instance
private static final SourceStructureBox INSTANCE = new SourceStructureBox(); private static final SourceStructureBox INSTANCE = new SourceStructureBox();
// Singleton source structure explorer child instance
// Source structure explorer private static ISourceStructureBox SUBINSTANCE;
private final SourceStructureExplorer sourceStructureExplorer;
/** /**
* Return the singleton source structure explorer box. * Return the singleton source structure explorer box.
...@@ -42,9 +41,12 @@ public final class SourceStructureBox extends Box { ...@@ -42,9 +41,12 @@ public final class SourceStructureBox extends Box {
false, // minimizable false, // minimizable
false); // removable false); // removable
sourceStructureExplorer = new SourceStructureExplorer(); // Creates the child instance according to the enabled features.
SUBINSTANCE = AppInventorFeatures.enableFutureFeatures()
? new SourceStructureBoxNew(this)
: new SourceStructureBoxClassic();
setContent(sourceStructureExplorer); setContent(SUBINSTANCE.getSourceStructureExplorer());
} }
/** /**
...@@ -53,15 +55,25 @@ public final class SourceStructureBox extends Box { ...@@ -53,15 +55,25 @@ public final class SourceStructureBox extends Box {
* @return source structure explorer * @return source structure explorer
*/ */
public SourceStructureExplorer getSourceStructureExplorer() { public SourceStructureExplorer getSourceStructureExplorer() {
return sourceStructureExplorer; return SUBINSTANCE.getSourceStructureExplorer();
} }
/**
* Calls the child box and renders it according to its behaviour.
* @param form current form
*/
public void show(MockForm form) { public void show(MockForm form) {
sourceStructureExplorer.updateTree(form.buildComponentsTree(), getSourceStructureExplorer().updateTree(form.buildComponentsTree(),
form.getLastSelectedComponent().getSourceStructureExplorerItem()); form.getLastSelectedComponent().getSourceStructureExplorerItem());
sourceStructureExplorer.setVisible(true); getSourceStructureBox().setVisible(true);
this.setVisible(true); setContent(SUBINSTANCE.getSourceStructureExplorer());
setContent(sourceStructureExplorer);
} }
/**
* Returns the header container for the source structure box (used by childs).
* @return DockPanel header container
*/
public DockPanel getHeaderContainer() {
return super.getHeaderContainer();
}
} }
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2023 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.client.boxes;
import com.google.appinventor.client.editor.simple.components.MockForm;
import com.google.appinventor.client.explorer.SourceStructureExplorer;
/**
* Box implementation for source structure explorer (classic style).
*/
public final class SourceStructureBoxClassic implements ISourceStructureBox {
private final SourceStructureExplorer sourceStructureExplorer = new SourceStructureExplorer();
public SourceStructureBoxClassic() {
super();
}
public void show(MockForm form) {
sourceStructureExplorer.updateTree(form.buildComponentsTree(),
form.getLastSelectedComponent().getSourceStructureExplorerItem());
sourceStructureExplorer.setVisible(true);
}
public SourceStructureExplorer getSourceStructureExplorer() {
return sourceStructureExplorer;
}
}
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2023 MIT, All rights reserved
// Released under the Apache License, Version 2.0
// http://www.apache.org/licenses/LICENSE-2.0
package com.google.appinventor.client.boxes;
import com.google.appinventor.client.Ode;
import com.google.appinventor.client.editor.simple.components.MockForm;
import com.google.appinventor.client.editor.youngandroid.YaFormEditor;
import com.google.appinventor.client.explorer.SourceStructureExplorer;
import com.google.appinventor.client.widgets.DropDownButton;
import com.google.appinventor.client.widgets.DropDownItem;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.DockPanel;
import java.util.ArrayList;
import java.util.List;
import static com.google.appinventor.client.Ode.MESSAGES;
/**
* Box implementation for source structure explorer (new style, with filters).
*/
public final class SourceStructureBoxNew implements ISourceStructureBox {
private Integer view = 1;
private final DropDownButton dropDownButton;
private final SourceStructureExplorer sourceStructureExplorer = new SourceStructureExplorer(false);
/**
* Creates new source structure explorer box.
*/
public SourceStructureBoxNew(SourceStructureBox container) {
super();
List<DropDownItem> items = new ArrayList<>();
items.add(new DropDownItem("AllComponents", MESSAGES.sourceStructureBoxCaptionAll(), new SelectSourceView(1)));
items.add(new DropDownItem("VisibleComponents", MESSAGES.sourceStructureBoxCaptionVisible(), new SelectSourceView(2)));
items.add(new DropDownItem("NonVisibleComponents", MESSAGES.sourceStructureBoxCaptionNonVisible(), new SelectSourceView(3)));
dropDownButton = new DropDownButton("ComponentsTreeFilter", "", items, false);
dropDownButton.addStyleName("components-tree-filter");
dropDownButton.setCaption(MESSAGES.sourceStructureBoxCaptionAll());
container.getHeaderContainer().clear();
container.getHeaderContainer().add(dropDownButton, DockPanel.LINE_START);
}
public void show(MockForm form) {
sourceStructureExplorer.updateTree(form.buildComponentsTree(view),
form.getLastSelectedComponent().getSourceStructureExplorerItem());
updateSourceDropdownButtonCaption();
sourceStructureExplorer.setVisible(true);
}
public SourceStructureExplorer getSourceStructureExplorer() {
return sourceStructureExplorer;
}
public void setView(Integer view) {
this.view = view;
}
public Integer getView() {
return view;
}
private void updateSourceDropdownButtonCaption() {
String c;
switch (view) {
case 1:
c = MESSAGES.sourceStructureBoxCaptionAll();
break;
case 2:
c = MESSAGES.sourceStructureBoxCaptionVisible();
break;
case 3:
c = MESSAGES.sourceStructureBoxCaptionNonVisible();
break;
default:
c = MESSAGES.sourceStructureBoxCaption();
break;
}
dropDownButton.setCaption(c);
}
private final class SelectSourceView implements Command {
/* 1 - > All components
* 2 - > Visible components
* 3 - > Non-visible components
*/
private final Integer view;
SelectSourceView(Integer view) {
super();
this.view = view;
}
@Override
public void execute() {
MockForm form = ((YaFormEditor) Ode.getInstance().getCurrentFileEditor()).getForm();
sourceStructureExplorer.updateTree(form.buildComponentsTree(view),
form.getForm().getLastSelectedComponent().getSourceStructureExplorerItem());
SourceStructureBoxNew.this.setView(view);
updateSourceDropdownButtonCaption();
}
}
}
...@@ -87,13 +87,23 @@ public abstract class MockContainer extends MockVisibleComponent implements Drop ...@@ -87,13 +87,23 @@ public abstract class MockContainer extends MockVisibleComponent implements Drop
return layout; return layout;
} }
@Override protected TreeItem buildTree(Integer view) {
protected TreeItem buildTree() {
TreeItem itemNode = super.buildTree(); TreeItem itemNode = super.buildTree();
//hide all containers except form if only nonvisible components are to be shown
//in such a case, we need only the form's treeItem because all non-visible components are attached to it
if (view == 3 && !isForm()) {
itemNode.setVisible(false);
}
// Recursively build the tree for child components // Recursively build the tree for child components
for (MockComponent child : children) { for (MockComponent child : children) {
itemNode.addItem(child.buildTree()); TreeItem childNode = child.buildTree();
if (view == 2 && child instanceof MockNonVisibleComponent) {
childNode.setVisible(false);
} else if (view == 3 && child instanceof MockVisibleComponent) {
childNode.setVisible(false);
}
itemNode.addItem(childNode);
} }
itemNode.setState(expanded); itemNode.setState(expanded);
......
...@@ -1341,7 +1341,17 @@ public final class MockForm extends MockContainer { ...@@ -1341,7 +1341,17 @@ public final class MockForm extends MockContainer {
* @return tree showing the component hierarchy of the form * @return tree showing the component hierarchy of the form
*/ */
public TreeItem buildComponentsTree() { public TreeItem buildComponentsTree() {
return buildTree(); return buildComponentsTree(1);
}
/**
* Builds a tree of the component hierarchy of the form for display in the
* {@code SourceStructureExplorer}.
*
* @return tree showing the component hierarchy of the form
*/
public TreeItem buildComponentsTree(Integer view) {
return buildTree(view);
} }
// PropertyChangeListener implementation // PropertyChangeListener implementation
......
...@@ -68,10 +68,14 @@ public class SourceStructureExplorer extends Composite { ...@@ -68,10 +68,14 @@ public class SourceStructureExplorer extends Composite {
} }
} }
public SourceStructureExplorer() {
this(true);
}
/** /**
* Creates a new source structure explorer. * Creates a new source structure explorer.
*/ */
public SourceStructureExplorer() { public SourceStructureExplorer(boolean includeButtonPanel) {
// Initialize UI elements // Initialize UI elements
tree = new EventCaptureTree(Ode.getImageBundle()); tree = new EventCaptureTree(Ode.getImageBundle());
tree.setAnimationEnabled(true); tree.setAnimationEnabled(true);
...@@ -174,8 +178,12 @@ public class SourceStructureExplorer extends Composite { ...@@ -174,8 +178,12 @@ public class SourceStructureExplorer extends Composite {
VerticalPanel panel = new VerticalPanel(); VerticalPanel panel = new VerticalPanel();
panel.add(scrollPanel); panel.add(scrollPanel);
// TODO(diego@kodular.io): With App Inventor's current layout, as of now this is the only place to
// render these buttons...
// if (includeButtonPanel) {
panel.add(new Label()); panel.add(new Label());
panel.add(buttonPanel); panel.add(buttonPanel);
// }
panel.setCellHorizontalAlignment(buttonPanel, HorizontalPanel.ALIGN_CENTER); panel.setCellHorizontalAlignment(buttonPanel, HorizontalPanel.ALIGN_CENTER);
initWidget(panel); initWidget(panel);
} }
......
...@@ -441,6 +441,14 @@ public abstract class Box extends HandlerPanel { ...@@ -441,6 +441,14 @@ public abstract class Box extends HandlerPanel {
return header; return header;
} }
/**
* Returns the box header container.
* @return header container
*/
public DockPanel getHeaderContainer() {
return headerContainer;
}
/** /**
* Invoked upon resizing of the box by the layout. Box height will remain * Invoked upon resizing of the box by the layout. Box height will remain
* unmodified. * unmodified.
......
...@@ -3142,3 +3142,9 @@ div.dropdiv p { ...@@ -3142,3 +3142,9 @@ div.dropdiv p {
.listItem:nth-child(2n + 0) { .listItem:nth-child(2n + 0) {
background: rgba(200, 200, 200, 0.1); background: rgba(200, 200, 200, 0.1);
} }
.components-tree-filter {
margin-top: 1px;
margin-left: 1px;
font-size: 11px;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment