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 {
@Description("Caption for source structure box.")
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)
@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; -*-
// 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
// http://www.apache.org/licenses/LICENSE-2.0
......@@ -9,20 +9,19 @@ package com.google.appinventor.client.boxes;
import static com.google.appinventor.client.Ode.MESSAGES;
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.boxes.Box;
import com.google.appinventor.common.version.AppInventorFeatures;
import com.google.gwt.user.client.ui.DockPanel;
/**
* 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
private static final SourceStructureBox INSTANCE = new SourceStructureBox();
// Source structure explorer
private final SourceStructureExplorer sourceStructureExplorer;
// Singleton source structure explorer child instance
private static ISourceStructureBox SUBINSTANCE;
/**
* Return the singleton source structure explorer box.
......@@ -42,9 +41,12 @@ public final class SourceStructureBox extends Box {
false, // minimizable
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 {
* @return source structure explorer
*/
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) {
sourceStructureExplorer.updateTree(form.buildComponentsTree(),
getSourceStructureExplorer().updateTree(form.buildComponentsTree(),
form.getLastSelectedComponent().getSourceStructureExplorerItem());
sourceStructureExplorer.setVisible(true);
this.setVisible(true);
setContent(sourceStructureExplorer);
getSourceStructureBox().setVisible(true);
setContent(SUBINSTANCE.getSourceStructureExplorer());
}
/**
* 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
return layout;
}
@Override
protected TreeItem buildTree() {
protected TreeItem buildTree(Integer view) {
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
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);
......
......@@ -1341,7 +1341,17 @@ public final class MockForm extends MockContainer {
* @return tree showing the component hierarchy of the form
*/
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
......
......@@ -68,10 +68,14 @@ public class SourceStructureExplorer extends Composite {
}
}
public SourceStructureExplorer() {
this(true);
}
/**
* Creates a new source structure explorer.
*/
public SourceStructureExplorer() {
public SourceStructureExplorer(boolean includeButtonPanel) {
// Initialize UI elements
tree = new EventCaptureTree(Ode.getImageBundle());
tree.setAnimationEnabled(true);
......@@ -174,8 +178,12 @@ public class SourceStructureExplorer extends Composite {
VerticalPanel panel = new VerticalPanel();
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(buttonPanel);
// }
panel.setCellHorizontalAlignment(buttonPanel, HorizontalPanel.ALIGN_CENTER);
initWidget(panel);
}
......
......@@ -441,6 +441,14 @@ public abstract class Box extends HandlerPanel {
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
* unmodified.
......
......@@ -3142,3 +3142,9 @@ div.dropdiv p {
.listItem:nth-child(2n + 0) {
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