// -*- mode: java; c-basic-offset: 2; -*- // Copyright 2009-2011 Google, All Rights reserved // Copyright 2011-2014 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.palette; import com.google.appinventor.client.ComponentsTranslation; import com.google.appinventor.client.editor.simple.SimpleComponentDatabase; import com.google.appinventor.client.editor.simple.components.MockComponent; import com.google.appinventor.client.editor.simple.components.utils.PropertiesUtil; import com.google.appinventor.client.editor.simple.palette.DropTargetProvider; import com.google.appinventor.client.editor.simple.palette.SimpleComponentDescriptor; import com.google.appinventor.client.editor.simple.palette.SimplePaletteItem; import com.google.appinventor.client.editor.simple.palette.SimplePalettePanel; import com.google.appinventor.client.editor.youngandroid.YaFormEditor; import com.google.appinventor.client.explorer.project.ComponentDatabaseChangeListener; import com.google.appinventor.client.wizards.ComponentImportWizard; import com.google.appinventor.common.version.AppInventorFeatures; import com.google.appinventor.components.common.ComponentCategory; import com.google.appinventor.shared.simple.ComponentDatabaseInterface.PropertyDefinition; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.StackPanel; import com.google.gwt.user.client.ui.VerticalPanel; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Panel showing Simple components which can be dropped onto the Young Android * visual designer panel. * * @author lizlooney@google.com (Liz Looney) */ public class YoungAndroidPalettePanel extends Composite implements SimplePalettePanel, ComponentDatabaseChangeListener { // Component database: information about components (including their properties and events) private final SimpleComponentDatabase COMPONENT_DATABASE; // Associated editor private final YaFormEditor editor; private final Map<ComponentCategory, PaletteHelper> paletteHelpers; private final StackPanel stackPalette; private final Map<ComponentCategory, VerticalPanel> categoryPanels; // store Component Type along with SimplePaleteItem to enable removal of components private final Map<String, SimplePaletteItem> simplePaletteItems; private DropTargetProvider dropTargetProvider; /** * Creates a new component palette panel. * * @param editor parent editor of this panel */ public YoungAndroidPalettePanel(YaFormEditor editor) { this.editor = editor; COMPONENT_DATABASE = SimpleComponentDatabase.getInstance(editor.getProjectId()); stackPalette = new StackPanel(); paletteHelpers = new HashMap<ComponentCategory, PaletteHelper>(); // If a category has a palette helper, add it to the paletteHelpers map here. paletteHelpers.put(ComponentCategory.LEGOMINDSTORMS, new LegoPaletteHelper()); categoryPanels = new HashMap<ComponentCategory, VerticalPanel>(); simplePaletteItems = new HashMap<String, SimplePaletteItem>(); for (ComponentCategory category : ComponentCategory.values()) { if (showCategory(category)) { VerticalPanel categoryPanel = new VerticalPanel(); categoryPanel.setWidth("100%"); categoryPanels.put(category, categoryPanel); stackPalette.add(categoryPanel, ComponentsTranslation.getCategoryName(category.getName())); } } initExtensionPanel(); stackPalette.setWidth("100%"); initWidget(stackPalette); } private static boolean showCategory(ComponentCategory category) { if (category == ComponentCategory.UNINITIALIZED) { return false; } if (category == ComponentCategory.INTERNAL && !AppInventorFeatures.showInternalComponentsCategory()) { return false; } return true; } /** * Loads all components to be shown on this palette. Specifically, for * each component (except for those whose category is UNINITIALIZED, or * whose category is INTERNAL and we're running on a production server, * or who are specifically marked as not to be shown on the palette), * this creates a corresponding {@link SimplePaletteItem} with the passed * {@link DropTargetProvider} and adds it to the panel corresponding to * its category. * * @param dropTargetProvider provider of targets that palette items can be * dropped on */ @Override public void loadComponents(DropTargetProvider dropTargetProvider) { this.dropTargetProvider = dropTargetProvider; for (String component : COMPONENT_DATABASE.getComponentNames()) { this.addComponent(component); } } public void loadComponents() { for (String component : COMPONENT_DATABASE.getComponentNames()) { this.addComponent(component); } } @Override public void configureComponent(MockComponent mockComponent) { String componentType = mockComponent.getType(); PropertiesUtil.populateProperties(mockComponent, COMPONENT_DATABASE.getPropertyDefinitions(componentType), editor); } /** * Loads a single Component to Palette. Used for adding Components. */ @Override public void addComponent(String componentTypeName) { if (simplePaletteItems.containsKey(componentTypeName)) { // We are upgrading removeComponent(componentTypeName); } String helpString = COMPONENT_DATABASE.getHelpString(componentTypeName); String helpUrl = COMPONENT_DATABASE.getHelpUrl(componentTypeName); String categoryDocUrlString = COMPONENT_DATABASE.getCategoryDocUrlString(componentTypeName); String categoryString = COMPONENT_DATABASE.getCategoryString(componentTypeName); Boolean showOnPalette = COMPONENT_DATABASE.getShowOnPalette(componentTypeName); Boolean nonVisible = COMPONENT_DATABASE.getNonVisible(componentTypeName); Boolean external = COMPONENT_DATABASE.getComponentExternal(componentTypeName); ComponentCategory category = ComponentCategory.valueOf(categoryString); if (showOnPalette && showCategory(category)) { SimplePaletteItem item = new SimplePaletteItem( new SimpleComponentDescriptor(componentTypeName, editor, helpString, helpUrl, categoryDocUrlString, showOnPalette, nonVisible, external), dropTargetProvider); simplePaletteItems.put(componentTypeName, item); addPaletteItem(item, category); } } public void removeComponent(String componentTypeName) { String categoryString = COMPONENT_DATABASE.getCategoryString(componentTypeName); ComponentCategory category = ComponentCategory.valueOf(categoryString); removePaletteItem(simplePaletteItems.get(componentTypeName), category); } /* * Adds a component entry to the palette. */ private void addPaletteItem(SimplePaletteItem component, ComponentCategory category) { VerticalPanel panel = categoryPanels.get(category); PaletteHelper paletteHelper = paletteHelpers.get(category); if (paletteHelper != null) { paletteHelper.addPaletteItem(panel, component); } else { panel.add(component); } } private void removePaletteItem(SimplePaletteItem component, ComponentCategory category) { VerticalPanel panel = categoryPanels.get(category); panel.remove(component); } private void initExtensionPanel() { Anchor addComponentAnchor = new Anchor("Import extension"); addComponentAnchor.setStylePrimaryName("ode-ExtensionAnchor"); addComponentAnchor.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { new ComponentImportWizard().center(); } }); categoryPanels.get(ComponentCategory.EXTENSION).add(addComponentAnchor); categoryPanels.get(ComponentCategory.EXTENSION).setCellHorizontalAlignment( addComponentAnchor, HasHorizontalAlignment.ALIGN_CENTER); } @Override public void onComponentTypeAdded(List<String> componentTypes) { for (String componentType : componentTypes) { this.addComponent(componentType); } } @Override public boolean beforeComponentTypeRemoved(List<String> componentTypes) { boolean result = true; for (String componentType : componentTypes) { this.removeComponent(componentType); } return result; } @Override public void onComponentTypeRemoved(Map<String, String> componentTypes) { } @Override public void onResetDatabase() { reloadComponents(); } @Override public void clearComponents() { for (ComponentCategory category : categoryPanels.keySet()) { VerticalPanel panel = categoryPanels.get(category); panel.clear(); } } @Override public void reloadComponents() { clearComponents(); loadComponents(); } }