// -*- 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.editor.youngandroid.properties; import static com.google.appinventor.client.Ode.MESSAGES; import com.google.appinventor.client.editor.simple.components.FormChangeListener; import com.google.appinventor.client.editor.simple.components.MockComponent; import com.google.appinventor.client.editor.youngandroid.YaFormEditor; import com.google.appinventor.client.widgets.properties.AdditionalChoicePropertyEditor; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.VerticalPanel; import java.util.Set; /** * Property editor for selecting a component for a property. * * @author lizlooney@google.com (Liz Looney) */ public final class YoungAndroidComponentSelectorPropertyEditor extends AdditionalChoicePropertyEditor implements FormChangeListener { // UI elements private final ListBox componentsList; private final ListWithNone choices; // The YaFormEditor associated with this property editor. private final YaFormEditor editor; // The types of component that can be chosen private final Set<String> componentTypes; /** * Creates a new property editor for selecting a component. * * @param editor the editor that this property editor belongs to */ public YoungAndroidComponentSelectorPropertyEditor(YaFormEditor editor) { this(editor, null); } /** * Creates a new property editor for selecting a component, where the * user chooses among components of one or more component types. * * @param editor the editor that this property editor belongs to * @param componentTypes types of component that can be selected, or null if * all types of components can be selected. */ public YoungAndroidComponentSelectorPropertyEditor(final YaFormEditor editor, Set<String> componentTypes) { this.editor = editor; this.componentTypes = componentTypes; VerticalPanel selectorPanel = new VerticalPanel(); componentsList = new ListBox(); componentsList.setVisibleItemCount(10); componentsList.setWidth("100%"); selectorPanel.add(componentsList); selectorPanel.setWidth("100%"); choices = new ListWithNone(MESSAGES.noneCaption(), new ListWithNone.ListBoxWrapper() { @Override public void addItem(String item) { componentsList.addItem(item); } @Override public String getItem(int index) { return componentsList.getItemText(index); } @Override public void removeItem(int index) { componentsList.removeItem(index); } @Override public void setSelectedIndex(int index) { componentsList.setSelectedIndex(index); } }); // At this point, the editor hasn't finished loading. // Use a DeferredCommand to finish the initialization after the editor has finished loading. DeferredCommand.addCommand(new Command() { @Override public void execute() { if (editor.isLoadComplete()) { finishInitialization(); } else { // Editor still hasn't finished loading. DeferredCommand.addCommand(this); } } }); initAdditionalChoicePanel(selectorPanel); } private void finishInitialization() { // Add a FormChangeListener so we'll know when components are added/removed/renamed. editor.getForm().addFormChangeListener(this); // Fill choices with the components. for (MockComponent component : editor.getComponents().values()) { if (componentTypes == null || componentTypes.contains(component.getType())) { choices.addItem(component.getName()); } } // Previous version had a bug where the value could be accidentally saved as "None". // If the property value is "None" and choices doesn't contain the value "None", set the // property value to "". String value = property.getValue(); if (value.equals("None") && !choices.containsValue(value)) { property.setValue(""); } } @Override public void orphan() { editor.getForm().removeFormChangeListener(this); super.orphan(); } @Override protected void openAdditionalChoiceDialog() { choices.selectValue(property.getValue()); super.openAdditionalChoiceDialog(); componentsList.setFocus(true); } @Override protected String getPropertyValueSummary() { String value = property.getValue(); if (choices.containsValue(value)) { return choices.getDisplayItemForValue(value); } return value; } @Override protected boolean okAction() { int selected = componentsList.getSelectedIndex(); if (selected == -1) { Window.alert(MESSAGES.noComponentSelected()); return false; } property.setValue(choices.getValueAtIndex(selected)); return true; } // FormChangeListener public void onComponentPropertyChanged(MockComponent component, String propertyName, String propertyValue) { } public void onComponentRemoved(MockComponent component, boolean permanentlyDeleted) { if (permanentlyDeleted) { if (componentTypes == null || componentTypes.contains(component.getType())) { String componentName = component.getName(); // Check whether our component was removed. String currentValue = property.getValue(); if (componentName.equals(currentValue)) { // Our component was removed. property.setValue(""); } // Remove the component from the list. choices.removeValue(componentName); } } } public void onComponentAdded(MockComponent component) { if (componentTypes == null || componentTypes.contains(component.getType())) { choices.addItem(component.getName()); } } public void onComponentRenamed(MockComponent component, String oldName) { if (componentTypes == null || componentTypes.contains(component.getType())) { String newName = component.getName(); // Add the new name to the list. choices.addItem(newName); // Check whether our component was renamed. String currentValue = property.getValue(); if (oldName.equals(currentValue)) { // Our component was renamed. property.setValue(newName); } // Remove the old name from the choices. choices.removeValue(oldName); } } public void onComponentSelectionChange(MockComponent component, boolean selected) { } }