// Switch to an existing project. Note that this does not switch screens.
 // TODO(sharon): it might be better to throw an exception if the
 // project doesn't exist.
 private boolean switchToProject(long projectId, String projectName) {
   if (projectMap.containsKey(projectId)) {
     DesignProject project = projectMap.get(projectId);
     if (project == currentProject) {
       OdeLog.wlog("DesignToolbar: ignoring call to switchToProject for current project");
       return true;
     }
     pushedScreens.clear(); // Effectively switching applications clear stack of screens
     clearDropDownMenu(WIDGET_NAME_SCREENS_DROPDOWN);
     OdeLog.log(
         "DesignToolbar: switching to existing project " + projectName + " with id " + projectId);
     currentProject = projectMap.get(projectId);
     // TODO(sharon): add screens to drop-down menu in the right order
     for (Screen screen : currentProject.screens.values()) {
       addDropDownButtonItem(
           WIDGET_NAME_SCREENS_DROPDOWN,
           new ToolbarItem(
               screen.screenName,
               screen.screenName,
               new SwitchScreenAction(projectId, screen.screenName)));
     }
     projectNameLabel.setText(projectName);
   } else {
     ErrorReporter.reportError(
         "Design toolbar doesn't know about project " + projectName + " with id " + projectId);
     OdeLog.wlog(
         "Design toolbar doesn't know about project " + projectName + " with id " + projectId);
     return false;
   }
   return true;
 }
 /*
  * Remove screen name (if it exists) from project projectId
  */
 public void removeScreen(long projectId, String name) {
   if (!projectMap.containsKey(projectId)) {
     OdeLog.wlog(
         "DesignToolbar can't find project "
             + name
             + " with id "
             + projectId
             + " Ignoring removeScreen().");
     return;
   }
   OdeLog.log("DesignToolbar: got removeScreen for project " + projectId + ", screen " + name);
   DesignProject project = projectMap.get(projectId);
   if (!project.screens.containsKey(name)) {
     // already removed this screen
     return;
   }
   if (currentProject == project) {
     // if removing current screen, choose a new screen to show
     if (currentProject.currentScreen.equals(name)) {
       // TODO(sharon): maybe make a better choice than screen1, but for now
       // switch to screen1 because we know it is always there
       switchToScreen(projectId, YoungAndroidSourceNode.SCREEN1_FORM_NAME, View.FORM);
     }
     removeDropDownButtonItem(WIDGET_NAME_SCREENS_DROPDOWN, name);
   }
   project.removeScreen(name);
 }
 public void addProject(long projectId, String projectName) {
   if (!projectMap.containsKey(projectId)) {
     projectMap.put(projectId, new DesignProject(projectName, projectId));
     OdeLog.log("DesignToolbar added project " + projectName + " with id " + projectId);
   } else {
     OdeLog.wlog(
         "DesignToolbar ignoring addProject for existing project "
             + projectName
             + " with id "
             + projectId);
   }
 }
 private void doSwitchScreen(long projectId, String screenName, View view) {
   if (!projectMap.containsKey(projectId)) {
     OdeLog.wlog(
         "DesignToolbar: no project with id "
             + projectId
             + ". Ignoring SwitchScreenAction.execute().");
     return;
   }
   DesignProject project = projectMap.get(projectId);
   if (currentProject != project) {
     // need to switch projects first. this will not switch screens.
     if (!switchToProject(projectId, project.name)) {
       return;
     }
     // currentProject == project now
   }
   String newScreenName = screenName;
   if (!currentProject.screens.containsKey(newScreenName)) {
     // Can't find the requested screen in this project. This shouldn't happen, but if it does
     // for some reason, try switching to Screen1 instead.
     OdeLog.wlog(
         "Trying to switch to non-existent screen "
             + newScreenName
             + " in project "
             + currentProject.name
             + ". Trying Screen1 instead.");
     if (currentProject.screens.containsKey(YoungAndroidSourceNode.SCREEN1_FORM_NAME)) {
       newScreenName = YoungAndroidSourceNode.SCREEN1_FORM_NAME;
     } else {
       // something went seriously wrong!
       ErrorReporter.reportError(
           "Something is wrong. Can't find Screen1 for project " + currentProject.name);
       return;
     }
   }
   currentView = view;
   Screen screen = currentProject.screens.get(newScreenName);
   ProjectEditor projectEditor = screen.formEditor.getProjectEditor();
   currentProject.setCurrentScreen(newScreenName);
   setDropDownButtonCaption(WIDGET_NAME_SCREENS_DROPDOWN, newScreenName);
   OdeLog.log("Setting currentScreen to " + newScreenName);
   if (currentView == View.FORM) {
     projectEditor.selectFileEditor(screen.formEditor);
     toggleEditor(false);
   } else { // must be View.BLOCKS
     projectEditor.selectFileEditor(screen.blocksEditor);
     toggleEditor(true);
   }
   // Inform the Blockly Panel which project/screen (aka form) we are working on
   BlocklyPanel.setCurrentForm(projectId + "_" + newScreenName);
   updateButtons();
 }
 public static String getName(String key) {
   if (!myMap.containsKey(key)) {
     OdeLog.log("Method map does not contain key " + key);
     return key;
   }
   return myMap.get(key);
 }
  /** Creates a new box registry. */
  public OdeBoxRegistry() {
    register(MessagesOutputBox.getMessagesOutputBox());

    if (OdeLog.isLogAvailable()) {
      register(OdeLogBox.getOdeLogBox());
    }
  }
  /** Given the drawerName, return the name in current language setting */
  private String getBuiltinDrawerNames(String drawerName) {
    String name;

    OdeLog.wlog("getBuiltinDrawerNames: drawerName = " + drawerName);

    if (drawerName.equals("Control")) {
      name = MESSAGES.builtinControlLabel();
    } else if (drawerName.equals("Logic")) {
      name = MESSAGES.builtinLogicLabel();
    } else if (drawerName.equals("Math")) {
      name = MESSAGES.builtinMathLabel();
    } else if (drawerName.equals("Text")) {
      name = MESSAGES.builtinTextLabel();
    } else if (drawerName.equals("Lists")) {
      name = MESSAGES.builtinListsLabel();
    } else if (drawerName.equals("Colors")) {
      name = MESSAGES.builtinColorsLabel();
    } else if (drawerName.equals("Variables")) {
      name = MESSAGES.builtinVariablesLabel();
    } else if (drawerName.equals("Procedures")) {
      name = MESSAGES.builtinProceduresLabel();
    } else {
      name = drawerName;
    }
    return name;
  }
 @Override
 public void saveSettings(final Command command) {
   if (loading) {
     // If we are in the process of loading, we must defer saving.
     DeferredCommand.addCommand(
         new Command() {
           @Override
           public void execute() {
             saveSettings(command);
           }
         });
   } else {
     String s = encodeSettings();
     OdeLog.log("Saving global settings: " + s);
     Ode.getInstance()
         .getUserInfoService()
         .storeUserSettings(
             s,
             new OdeAsyncCallback<Void>(
                 // failure message
                 MESSAGES.settingsSaveError()) {
               @Override
               public void onSuccess(Void result) {
                 if (command != null) {
                   command.execute();
                 }
               }
             });
   }
 }
 @Override
 public void execute() {
   if (currentProject == null) {
     OdeLog.wlog(
         "DesignToolbar.currentProject is null. " + "Ignoring WirelessAction.execute().");
     return;
   }
   startRepl(currentProject.currentScreen, false, true);
 }
 @Override
 public void execute(final ProjectNode node) {
   // Display a barcode for an url pointing at our server's download servlet
   String barcodeUrl =
       CHARTSERVER_BARCODE_URI
           + GWT.getModuleBaseURL()
           + ServerLayout.genRelativeDownloadPath(node.getProjectId(), target);
   OdeLog.log("Barcode url is: " + barcodeUrl);
   new BarcodeDialogBox(node.getName(), barcodeUrl).center();
 }
 private void replHardReset() {
   DesignToolbar.DesignProject currentProject =
       Ode.getInstance().getDesignToolbar().getCurrentProject();
   if (currentProject == null) {
     OdeLog.wlog("DesignToolbar.currentProject is null. " + "Ignoring attempt to do hard reset.");
     return;
   }
   DesignToolbar.Screen screen = currentProject.screens.get(currentProject.currentScreen);
   ((YaBlocksEditor) screen.blocksEditor).hardReset();
   updateConnectToDropDownButton(false, false, false);
 }
 @Override
 public void execute() {
   if (currentProject == null) {
     OdeLog.wlog(
         "DesignToolbar.currentProject is null. "
             + "Ignoring SwitchToFormEditorAction.execute().");
     return;
   }
   if (currentView != View.FORM) {
     long projectId = Ode.getInstance().getCurrentYoungAndroidProjectRootNode().getProjectId();
     switchToScreen(projectId, currentProject.currentScreen, View.FORM);
     toggleEditor(false); // Gray out the Designer button and enable the blocks button
   }
 }
  @Override
  public void saveSettings(final Command command) {
    if (Ode.getInstance().isReadOnly()) {
      return; // Don't save when in read-only mode
    }
    if (loading) {
      // If we are in the process of loading, we must defer saving.
      DeferredCommand.addCommand(
          new Command() {
            @Override
            public void execute() {
              saveSettings(command);
            }
          });
    } else if (!loaded) {
      // Do not save settings that have not been loaded. We should
      // only wind up in this state if we are in the early phases of
      // loading the App Inventor client code. If saveSettings is
      // called in this state, it is from the onWindowClosing
      // handler. We do *not* want to over-write a persons valid
      // settings with this empty version, so we just return.
      return;

    } else {
      String s = encodeSettings();
      OdeLog.log("Saving global settings: " + s);
      Ode.getInstance()
          .getUserInfoService()
          .storeUserSettings(
              s,
              new OdeAsyncCallback<Void>(
                  // failure message
                  MESSAGES.settingsSaveError()) {
                @Override
                public void onSuccess(Void result) {
                  if (command != null) {
                    command.execute();
                  }
                }
              });
    }
  }
 /*
  * Add a screen name to the drop-down for the project with id projectId.
  * name is the form name, formEditor is the file editor for the form UI,
  * and blocksEditor is the file editor for the form's blocks.
  */
 public void addScreen(
     long projectId, String name, FileEditor formEditor, FileEditor blocksEditor) {
   if (!projectMap.containsKey(projectId)) {
     OdeLog.wlog(
         "DesignToolbar can't find project "
             + name
             + " with id "
             + projectId
             + ". Ignoring addScreen().");
     return;
   }
   DesignProject project = projectMap.get(projectId);
   if (project.addScreen(name, formEditor, blocksEditor)) {
     if (currentProject == project) {
       addDropDownButtonItem(
           WIDGET_NAME_SCREENS_DROPDOWN,
           new ToolbarItem(name, name, new SwitchScreenAction(projectId, name)));
     }
   }
 }
 /**
  * startRepl -- Start/Stop the connection to the companion.
  *
  * @param start -- true to start the repl, false to stop it.
  * @param forEmulator -- true if we are connecting to the emulator.
  * @param forUsb -- true if this is a USB connection.
  *     <p>If both forEmulator and forUsb are false, then we are connecting via Wireless.
  */
 private void startRepl(boolean start, boolean forEmulator, boolean forUsb) {
   DesignToolbar.DesignProject currentProject =
       Ode.getInstance().getDesignToolbar().getCurrentProject();
   if (currentProject == null) {
     OdeLog.wlog("DesignToolbar.currentProject is null. " + "Ignoring attempt to start the repl.");
     return;
   }
   DesignToolbar.Screen screen = currentProject.screens.get(currentProject.currentScreen);
   screen.blocksEditor.startRepl(!start, forEmulator, forUsb);
   if (start) {
     if (forEmulator) { // We are starting the emulator...
       updateConnectToDropDownButton(true, false, false);
     } else if (forUsb) { // We are starting the usb connection
       updateConnectToDropDownButton(false, false, true);
     } else { // We are connecting via wifi to a Companion
       updateConnectToDropDownButton(false, true, false);
     }
   } else {
     updateConnectToDropDownButton(false, false, false);
   }
 }
 /**
  * Upgrades the given sourceProperties if necessary.
  *
  * @param sourceProperties the properties from the source file
  * @return true if the sourceProperties was upgraded, false otherwise
  */
 public static boolean upgradeSourceProperties(Map<String, JSONValue> sourceProperties) {
   StringBuilder upgradeDetails = new StringBuilder();
   try {
     int srcYaVersion = getSrcYaVersion(sourceProperties);
     if (needToUpgrade(srcYaVersion)) {
       Map<String, JSONValue> formProperties =
           sourceProperties.get("Properties").asObject().getProperties();
       upgradeComponent(srcYaVersion, formProperties, upgradeDetails);
       // The sourceProperties were upgraded. Update the version number.
       setSrcYaVersion(sourceProperties);
       if (upgradeDetails.length() > 0) {
         Window.alert(MESSAGES.projectWasUpgraded(upgradeDetails.toString()));
       }
       return true;
     }
   } catch (LoadException e) {
     // This shouldn't happen. If it does it's our fault, not the user's fault.
     Window.alert(MESSAGES.unexpectedProblem(e.getMessage()));
     OdeLog.xlog(e);
   }
   return false;
 }
  private static void unquotePropertyValues(
      Map<String, JSONValue> componentProperties, String componentType) {
    // From the component database, get the map of property names and types for the component type.
    Map<String, String> propertyTypesByName =
        COMPONENT_DATABASE.getPropertyTypesByName(componentType);

    // Iterate through the component properties.
    for (String propertyName : componentProperties.keySet()) {
      // Get the property type.
      String propertyType = propertyTypesByName.get(propertyName);
      // In theory the check for propertyType == null shouldn't be necessary
      // but I have sometimes had a problem with it being null when running
      // with GWT debugging. Maybe it changes the timing somehow. Anyway,
      // this test for null should not hurt anything. -Sharon
      if (propertyType == null) {
        OdeLog.wlog(
            "Couldn't find propertyType for property "
                + propertyName
                + " in component type "
                + componentType);
        continue;
      }
      // If the property type is one that was previously quoted, unquote the value.
      if (propertyType.equals("asset")
          || propertyType.equals("BluetoothClient")
          || propertyType.equals("component")
          || propertyType.equals("lego_nxt_sensor_port")
          || propertyType.equals("string")) {
        // Unquote the property value.
        JSONValue propertyValue = componentProperties.get(propertyName);
        String propertyValueString = propertyValue.asString().getString();
        propertyValueString = StringUtils.unquote(propertyValueString);
        componentProperties.put(propertyName, new ClientJsonString(propertyValueString));
      }
    }
  }