diff --git a/appinventor/appengine/src/com/google/appinventor/client/Ode.java b/appinventor/appengine/src/com/google/appinventor/client/Ode.java
index ca858387ba9..02352615377 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/Ode.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/Ode.java
@@ -20,6 +20,7 @@
import com.google.appinventor.client.editor.EditorManager;
import com.google.appinventor.client.editor.FileEditor;
import com.google.appinventor.client.editor.ProjectEditor;
+import com.google.appinventor.client.editor.simple.components.MockComponent;
import com.google.appinventor.client.editor.simple.palette.DropTargetProvider;
import com.google.appinventor.client.editor.youngandroid.BlocklyPanel;
import com.google.appinventor.client.editor.youngandroid.DesignToolbar;
@@ -83,7 +84,11 @@
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.RunAsyncCallback;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.MouseWheelEvent;
import com.google.gwt.event.dom.client.MouseWheelHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
@@ -95,6 +100,7 @@
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
@@ -118,6 +124,8 @@
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.widgetideas.client.event.KeyDownHandler;
+
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -1616,6 +1624,15 @@ public DialogBox createEmptyTrashDialog(boolean showDialog) {
dialogBox.show();
}
+ Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
+ @Override
+ public void onPreviewNativeEvent(Event.NativePreviewEvent event) {
+ if (event.getTypeInt() == Event.ONKEYDOWN && dialogBox.isShowing()) {
+ dialogBox.hide();
+ }
+ }
+ });
+
return dialogBox;
}
@@ -1642,7 +1659,7 @@ private void createWelcomeDialog(final boolean force) {
return;
}
// Create the UI elements of the DialogBox
- final DialogBox dialogBox = new DialogBox(false, true); // DialogBox(autohide, modal)
+ final DialogBox dialogBox = new DialogBox(false, false); // DialogBox(autohide, modal)
dialogBox.setStylePrimaryName("ode-DialogBox");
dialogBox.setText(MESSAGES.createWelcomeDialogText());
dialogBox.setHeight(splashConfig.height + "px");
@@ -1673,7 +1690,16 @@ public void onClick(Widget sender) {
DialogBoxContents.add(message);
DialogBoxContents.add(holder);
dialogBox.setWidget(DialogBoxContents);
+ ok.setFocus(true);
dialogBox.show();
+
+ Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
+ public void onPreviewNativeEvent(NativePreviewEvent event) {
+ if (event.getTypeInt() == Event.ONKEYDOWN && event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE && dialogBox.isShowing()) {
+ dialogBox.hide();
+ }
+ }
+ });
}
/**
diff --git a/appinventor/appengine/src/com/google/appinventor/client/OdeMessages.java b/appinventor/appengine/src/com/google/appinventor/client/OdeMessages.java
index 6d5ca3d1ba4..e4180713f0f 100755
--- a/appinventor/appengine/src/com/google/appinventor/client/OdeMessages.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/OdeMessages.java
@@ -660,7 +660,7 @@ public interface OdeMessages extends Messages, ComponentTranslations {
@Description("Message providing details about starting a USB connection.")
String usbMenuItem();
- @DefaultMessage("Reset Connection")
+ @DefaultMessage("Reset Connection (Alt + Shift + R)")
@Description("Reset all connections.")
String resetConnectionsMenuItem();
@@ -668,7 +668,7 @@ public interface OdeMessages extends Messages, ComponentTranslations {
@Description("Hard Reset the Emulator.")
String hardResetConnectionsMenuItem();
- @DefaultMessage("Refresh Companion Screen")
+ @DefaultMessage("Refresh Companion Screen (Alt + R)")
@Description("Refresh the companion screen.")
String refreshCompanionMenuItem();
@@ -730,6 +730,10 @@ public interface OdeMessages extends Messages, ComponentTranslations {
@Description("Redisplay the Splash Screen")
String showSplashMenuItem();
+ @DefaultMessage("Show Keyboard Shortcuts (Alt + ?)")
+ @Description("Display the Shortcuts dialog")
+ String showShortcuts();
+
@DefaultMessage("Library")
@Description("Name of Library link")
String libraryMenuItem();
@@ -1275,7 +1279,7 @@ public interface OdeMessages extends Messages, ComponentTranslations {
String blocksLoadFailure(String formName);
// Used in editor/youngandroid/palette/YoungAndroidPalettePanel.java
- @DefaultMessage("Search Components...")
+ @DefaultMessage("Type / to search components")
@Description("Text shown in the component palette search box")
String searchComponents();
@@ -5140,6 +5144,32 @@ String newerVersionComponentException(String componentType, int srcCompVersion,
@Description("")
String MaximumRangeMethods();
+ @DefaultMessage(
+ "
" +
+ "" +
+ "" +
+ "Action | " +
+ "Key Combination | " +
+ "
" +
+ "" +
+ "" +
+ "Focus Component search box | / |
" +
+ "Focus Components tree | T |
" +
+ "Focus Viewer | V |
" +
+ "Focus Properties Panel | P |
" +
+ "Focus Media Panel | M |
" +
+ "Switch between Designer and Block editor | Ctrl + Alt |
" +
+ "Rename Component | Alt + N |
" +
+ "Delete Component | Delete/Backspace |
" +
+ "Reset Connection | Alt + Shift + R |
" +
+ "Refresh Companion Screen | Alt + R |
" +
+ "Navigate Components in components tree | ↑/↓ |
" +
+ "Open this dialog | Alt + ? |
" +
+ "" +
+ "
")
+ @Description("")
+ String KeyBoardShortcuts();
+
// =========== ListPicker
@DefaultMessage("ItemTextColor")
@Description("")
diff --git a/appinventor/appengine/src/com/google/appinventor/client/TopToolbar.ui.xml b/appinventor/appengine/src/com/google/appinventor/client/TopToolbar.ui.xml
index 2aa69d60778..ffd6f977382 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/TopToolbar.ui.xml
+++ b/appinventor/appengine/src/com/google/appinventor/client/TopToolbar.ui.xml
@@ -174,6 +174,9 @@
+
+
+
diff --git a/appinventor/appengine/src/com/google/appinventor/client/actions/ShowShortcutsAction.java b/appinventor/appengine/src/com/google/appinventor/client/actions/ShowShortcutsAction.java
new file mode 100644
index 00000000000..22bb843c6e5
--- /dev/null
+++ b/appinventor/appengine/src/com/google/appinventor/client/actions/ShowShortcutsAction.java
@@ -0,0 +1,79 @@
+// -*- 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.actions;
+
+import static com.google.appinventor.client.Ode.MESSAGES;
+
+import com.google.appinventor.client.Ode;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.Event;
+import com.google.gwt.user.client.ui.Button;
+import com.google.gwt.user.client.ui.DialogBox;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.VerticalPanel;
+
+public class ShowShortcutsAction implements Command {
+
+ private DialogBox db;
+
+ public ShowShortcutsAction() {
+ db = new DialogBox(true, false);
+ db.setText("Keyboard Shortcuts");
+ db.setStyleName("ode-DialogBox");
+ db.setHeight("200px");
+ db.setWidth("400px");
+ db.setGlassEnabled(true);
+ db.setAnimationEnabled(true);
+
+ shortcutKeyHandler();
+ }
+
+ @Override
+ public void execute() {
+ VerticalPanel DialogBoxContents = new VerticalPanel();
+ HTML message = new HTML(MESSAGES.KeyBoardShortcuts());
+ Button button = new Button(Ode.MESSAGES.okButton());
+ button.addClickHandler(event -> db.hide());
+ DialogBoxContents.add(message);
+ DialogBoxContents.add(button);
+ db.setWidget(DialogBoxContents);
+ db.center();
+ db.show();
+ button.setFocus(true);
+ }
+
+ private void shortcutKeyHandler() {
+ Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
+ @Override
+ public void onPreviewNativeEvent(Event.NativePreviewEvent event) {
+ NativeEvent nativeEvent = event.getNativeEvent();
+ if (event.getTypeInt() == Event.ONKEYDOWN) {
+ if (nativeEvent.getKeyCode() == 191 && nativeEvent.getAltKey()) {
+ shortcutPressed();
+ }
+ if (nativeEvent.getKeyCode() == KeyCodes.KEY_ESCAPE) {
+ escPressed();
+ }
+ }
+ }
+ });
+ }
+
+ private void shortcutPressed() {
+ if (!db.isShowing()) {
+ execute();
+ }
+ }
+
+ private void escPressed() {
+ if (db.isShowing()) {
+ db.hide();
+ }
+ }
+}
\ No newline at end of file
diff --git a/appinventor/appengine/src/com/google/appinventor/client/editor/simple/SimpleVisibleComponentsPanel.java b/appinventor/appengine/src/com/google/appinventor/client/editor/simple/SimpleVisibleComponentsPanel.java
index f7353ba1131..5498d24317d 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/editor/simple/SimpleVisibleComponentsPanel.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/editor/simple/SimpleVisibleComponentsPanel.java
@@ -20,6 +20,7 @@
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
+import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
@@ -42,6 +43,7 @@ interface SimpleVisibleComponentsPanelUiBinder extends UiBinder
-
+
diff --git a/appinventor/appengine/src/com/google/appinventor/client/editor/simple/components/MockComponent.java b/appinventor/appengine/src/com/google/appinventor/client/editor/simple/components/MockComponent.java
index 48321ae4f3d..090368e50ef 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/editor/simple/components/MockComponent.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/editor/simple/components/MockComponent.java
@@ -12,6 +12,7 @@
import com.google.appinventor.client.editor.simple.components.i18n.ComponentTranslationTable;
import com.google.appinventor.client.Images;
import com.google.appinventor.client.Ode;
+import com.google.appinventor.client.boxes.SourceStructureBox;
import com.google.appinventor.client.editor.simple.SimpleEditor;
import com.google.appinventor.client.editor.simple.components.utils.PropertiesUtil;
import com.google.appinventor.client.editor.youngandroid.YaBlocksEditor;
@@ -39,10 +40,12 @@
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.DomEvent;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.HasAllTouchHandlers;
import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.TouchCancelHandler;
import com.google.gwt.event.dom.client.TouchEndHandler;
import com.google.gwt.event.dom.client.TouchMoveHandler;
@@ -110,12 +113,15 @@ private class RenameDialog extends DialogBox {
private final LabeledTextBox newNameTextBox;
RenameDialog(String oldName) {
- super(false, true);
-
+ super(false, false);
+ setGlassEnabled(true);
setStylePrimaryName("ode-DialogBox");
setText(MESSAGES.renameTitle());
VerticalPanel contentPanel = new VerticalPanel();
+ Button topInvisible = new Button();
+ contentPanel.add(topInvisible);
+
LabeledTextBox oldNameTextBox = new LabeledTextBox(MESSAGES.oldNameLabel());
oldNameTextBox.setText(getName());
oldNameTextBox.setEnabled(false);
@@ -123,9 +129,9 @@ private class RenameDialog extends DialogBox {
newNameTextBox = new LabeledTextBox(MESSAGES.newNameLabel());
newNameTextBox.setText(oldName);
- newNameTextBox.getTextBox().addKeyUpHandler(new KeyUpHandler() {
+ newNameTextBox.getTextBox().addKeyDownHandler(new KeyDownHandler() {
@Override
- public void onKeyUp(KeyUpEvent event) {
+ public void onKeyDown(KeyDownEvent event) {
int keyCode = event.getNativeKeyCode();
if (keyCode == KeyCodes.KEY_ENTER) {
handleOkClick();
@@ -150,9 +156,26 @@ public void onClick(ClickEvent event) {
handleOkClick();
}
});
+
+ Button bottomInvisible = new Button();
+ bottomInvisible.setStyleName("FocusTrap");
+ topInvisible.setStyleName("FocusTrap");
+ topInvisible.addFocusHandler(new FocusHandler() {
+ @Override
+ public void onFocus(FocusEvent event) {
+ okButton.setFocus(true);
+ }
+ });
+ bottomInvisible.addFocusHandler(new FocusHandler() {
+ public void onFocus(FocusEvent event) {
+ newNameTextBox.setFocus(true);
+ }
+ });
+
HorizontalPanel buttonPanel = new HorizontalPanel();
buttonPanel.add(cancelButton);
buttonPanel.add(okButton);
+ buttonPanel.add(bottomInvisible);
buttonPanel.setSize("100%", "24px");
contentPanel.add(buttonPanel);
contentPanel.setSize("320px", "100%");
@@ -227,8 +250,9 @@ public void execute() {
* This class defines the dialog box for deleting a component.
*/
private class DeleteDialog extends DialogBox {
+ private final Button deleteButton;
DeleteDialog() {
- super(false, true);
+ super(false, false);
setStylePrimaryName("ode-DialogBox");
setText(MESSAGES.deleteComponentButton());
@@ -242,13 +266,14 @@ public void onClick(ClickEvent event) {
hide();
}
});
- Button deleteButton = new Button(MESSAGES.deleteButton());
+ deleteButton = new Button(MESSAGES.deleteButton());
deleteButton.addStyleName("destructive-action");
deleteButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
hide();
MockComponent.this.delete();
+ SourceStructureBox.getSourceStructureBox().getSourceStructureExplorer().getTree().setFocus(true);
}
});
HorizontalPanel buttonPanel = new HorizontalPanel();
@@ -263,17 +288,15 @@ public void onClick(ClickEvent event) {
@Override
protected void onPreviewNativeEvent(NativePreviewEvent event) {
super.onPreviewNativeEvent(event);
- switch (event.getTypeInt()) {
- case Event.ONKEYDOWN:
- if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) {
- hide();
- } else if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
- hide();
- MockComponent.this.delete();
- }
- break;
+ if (event.getTypeInt() == Event.ONKEYDOWN && event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ESCAPE) {
+ hide();
}
}
+
+ public void center() {
+ super.center();
+ deleteButton.setFocus(true);
+ }
}
// Component database: information about components (including their properties and events)
diff --git a/appinventor/appengine/src/com/google/appinventor/client/editor/simple/components/MockVisibleComponent.java b/appinventor/appengine/src/com/google/appinventor/client/editor/simple/components/MockVisibleComponent.java
index ecd43350965..2b37adc8b05 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/editor/simple/components/MockVisibleComponent.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/editor/simple/components/MockVisibleComponent.java
@@ -9,6 +9,7 @@
import static com.google.appinventor.client.Ode.MESSAGES;
import com.google.appinventor.client.editor.simple.SimpleEditor;
+import com.google.appinventor.client.editor.simple.SimpleNonVisibleComponentsPanel;
import com.google.appinventor.client.editor.youngandroid.properties.YoungAndroidLengthPropertyEditor;
import com.google.appinventor.client.widgets.properties.TextPropertyEditor;
import com.google.appinventor.components.common.ComponentConstants;
@@ -157,4 +158,9 @@ public void onPropertyChange(String propertyName, String newValue) {
refreshForm();
}
}
-}
+
+ public SimpleNonVisibleComponentsPanel getNonVisibleComponentsPanel() {
+ return editor.getNonVisibleComponentsPanel();
+ }
+
+}
\ No newline at end of file
diff --git a/appinventor/appengine/src/com/google/appinventor/client/editor/simple/palette/SimplePaletteItem.java b/appinventor/appengine/src/com/google/appinventor/client/editor/simple/palette/SimplePaletteItem.java
index 688feeaf003..3bf1d95f7dd 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/editor/simple/palette/SimplePaletteItem.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/editor/simple/palette/SimplePaletteItem.java
@@ -9,9 +9,19 @@
import com.google.appinventor.client.editor.simple.components.i18n.ComponentTranslationTable;
import com.google.appinventor.client.editor.simple.components.MockComponent;
import com.google.appinventor.client.editor.simple.components.MockComponentsUtil;
+import com.google.appinventor.client.editor.simple.components.MockContainer;
+import com.google.appinventor.client.editor.simple.components.MockForm;
+import com.google.appinventor.client.editor.simple.components.MockVisibleComponent;
import com.google.appinventor.client.widgets.dnd.DragSourcePanel;
import com.google.appinventor.client.widgets.dnd.DragSourceSupport;
import com.google.appinventor.client.widgets.dnd.DropTarget;
+import com.google.gwt.event.dom.client.DoubleClickEvent;
+import com.google.gwt.event.dom.client.DoubleClickHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.TouchStartEvent;
@@ -114,6 +124,40 @@ public void onTouchStart(TouchStartEvent event) {
select(getWidget());
}
});
+ addFocusHandler(new FocusHandler() {
+ @Override
+ public void onFocus(FocusEvent event) {
+ select(getWidget());
+ }
+ });
+ addKeyDownHandler(new KeyDownHandler() {
+ @Override
+ public void onKeyDown (KeyDownEvent event) {
+ if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
+ addComponent();
+ }
+ }
+ });
+ addDoubleClickHandler(new DoubleClickHandler() {
+ public void onDoubleClick (DoubleClickEvent event) {
+ addComponent();
+ }
+ });
+ }
+
+ private void addComponent() {
+ MockComponent component = createMockComponent();
+ MockVisibleComponent mockVisibleComponent = (MockVisibleComponent) dropTargetProvider.getDropTargets()[0];
+ MockForm form = mockVisibleComponent.getForm();
+ MockComponent selectedComponent = form.getLastSelectedComponent();
+ if (selectedComponent instanceof MockContainer && ((MockContainer) selectedComponent).willAcceptComponentType(component.getType()) && component.isVisibleComponent()) {
+ ((MockContainer) selectedComponent).addComponent(component);
+ } else if (form.willAcceptComponentType(component.getType()) && component.isVisibleComponent()) {
+ form.addComponent(component);
+ } else if (form.willAcceptComponentType(component.getType()) && !component.isVisibleComponent()) {
+ form.addComponent(component);
+ form.getNonVisibleComponentsPanel().addComponent(component);
+ }
}
/**
diff --git a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/DesignToolbar.java b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/DesignToolbar.java
index 7cb27c05169..bea8504187d 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/DesignToolbar.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/DesignToolbar.java
@@ -11,6 +11,8 @@
import com.google.appinventor.client.editor.FileEditor;
import com.google.appinventor.client.editor.ProjectEditor;
import com.google.appinventor.client.editor.youngandroid.actions.SwitchScreenAction;
+import com.google.appinventor.client.editor.youngandroid.actions.SwitchToBlocksEditorAction;
+import com.google.appinventor.client.editor.youngandroid.actions.SwitchToFormEditorAction;
import com.google.appinventor.client.widgets.DropDownButton;
import com.google.appinventor.client.widgets.DropDownItem;
import com.google.appinventor.client.widgets.Toolbar;
@@ -21,9 +23,12 @@
import com.google.common.collect.Maps;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.RootPanel;
import java.util.LinkedList;
import java.util.Map;
@@ -160,6 +165,7 @@ public DesignToolbar() {
// Gray out the Designer button and enable the blocks button
toggleEditor(false);
Ode.getInstance().getTopToolbar().updateFileMenuButtons(0);
+ toggleView();
}
public void bindUI() {
@@ -369,6 +375,22 @@ public void toggleEditor(boolean blocks) {
setButtonEnabled(WIDGET_NAME_REMOVEFORM, notOnScreen1);
}
+ public void toggleView() {
+ SwitchToBlocksEditorAction blockView = new SwitchToBlocksEditorAction();
+ SwitchToFormEditorAction designView = new SwitchToFormEditorAction();
+ RootPanel.get().addDomHandler(new KeyDownHandler() {
+ public void onKeyDown(KeyDownEvent event) {
+ if (event.isControlKeyDown() && event.isAltKeyDown()) {
+ if (currentView == DesignToolbar.View.FORM) {
+ blockView.execute();
+ } else if (currentView == DesignToolbar.View.BLOCKS) {
+ designView.execute();
+ }
+ }
+ }
+ }, KeyDownEvent.getType());
+ }
+
public DesignProject getCurrentProject() {
return currentProject;
}
diff --git a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/YaFormEditor.java b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/YaFormEditor.java
index 78189f9a2e7..af45ecc9bc2 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/YaFormEditor.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/YaFormEditor.java
@@ -15,6 +15,7 @@
import com.google.appinventor.client.boxes.PaletteBox;
import com.google.appinventor.client.boxes.PropertiesBox;
import com.google.appinventor.client.boxes.SourceStructureBox;
+import com.google.appinventor.client.boxes.AssetListBox;
import com.google.appinventor.client.editor.ProjectEditor;
import com.google.appinventor.client.editor.simple.ComponentNotFoundException;
import com.google.appinventor.client.editor.simple.SimpleComponentDatabase;
@@ -56,12 +57,17 @@
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
+import com.google.gwt.event.dom.client.KeyCodes;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.DockPanel;
+import com.google.gwt.user.client.ui.RootPanel;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -199,6 +205,7 @@ public DropTarget[] getDropTargets() {
initWidget(componentsPanel);
setSize("100%", "100%");
registerNativeListeners();
+ registerKeyDownListeners();
}
public boolean shouldDisplayHiddenComponents() {
@@ -939,6 +946,90 @@ public void onResetDatabase() {
}
}
+
+ private void registerKeyDownListeners () {
+ RootPanel.get().addDomHandler(new KeyDownHandler() {
+ @Override
+ public void onKeyDown(KeyDownEvent event) {
+ if (event.isAltKeyDown() && isActiveEditor()) {
+ List allComponents = new ArrayList<>(getComponents().values());
+ MockComponent selectedComponent = form.getLastSelectedComponent();
+ int index = form.getChildren().indexOf(selectedComponent);
+
+ if (selectedComponent.isVisibleComponent()) {
+ switch (event.getNativeKeyCode()) {
+ case KeyCodes.KEY_DOWN:
+ if (index < 0) {
+ MockContainer container = selectedComponent.getContainer();
+ List containerComponents = container.getChildren();
+ int indexC = containerComponents.indexOf(selectedComponent);
+ int indexOfContainer = allComponents.indexOf(container);
+ selectedComponent.getContainer().removeComponent(selectedComponent, false);
+
+ if (indexC == containerComponents.size() && container.getContainer().willAcceptComponentType(selectedComponent.getType())) {
+ container.getContainer().addVisibleComponent(selectedComponent, indexOfContainer);
+ } else {
+ container.addVisibleComponent(selectedComponent, indexC + 1);
+ }
+ } else {
+ index++;
+ form.removeComponent(selectedComponent, false);
+ MockComponent nextComponent = allComponents.get(index + 1);
+ int nextComponentindex = form.getChildren().indexOf(nextComponent);
+ if(nextComponent instanceof MockContainer && ((MockContainer) nextComponent).willAcceptComponentType(selectedComponent.getType())) {
+ ((MockContainer)nextComponent).addVisibleComponent(selectedComponent, 0);
+ } else if (nextComponentindex < 0 && ((MockContainer) nextComponent.getContainer()).willAcceptComponentType(selectedComponent.getType())) {
+ nextComponent.getContainer().addVisibleComponent(selectedComponent, 0);
+ } else {
+ form.addVisibleComponent(selectedComponent, index);
+ }
+ }
+ break;
+
+ case KeyCodes.KEY_UP:
+ if (index < 0) {
+ MockContainer container = selectedComponent.getContainer();
+ List containerComponents = container.getChildren();
+ int indexC = containerComponents.indexOf(selectedComponent);
+ int indexOfContainer = allComponents.indexOf(container);
+ selectedComponent.getContainer().removeComponent(selectedComponent, false);
+ if (indexC == 0 && container.getContainer().willAcceptComponentType(selectedComponent.getType())) {
+ container.getContainer().addVisibleComponent(selectedComponent, indexOfContainer - 1);
+ } else {
+ container.addVisibleComponent(selectedComponent, indexC - 1);
+ }
+ } else {
+ index++;
+ form.removeComponent(selectedComponent, false);
+ MockComponent prevComponent = allComponents.get(index - 1);
+ int prevComponentIndex = form.getChildren().indexOf(prevComponent);
+ if(prevComponent instanceof MockContainer && ((MockContainer) prevComponent).willAcceptComponentType(selectedComponent.getType())) {
+ ((MockContainer)prevComponent).addVisibleComponent(selectedComponent, -1);
+ } else if (prevComponentIndex < 0 && ((MockContainer) prevComponent).willAcceptComponentType(selectedComponent.getType())) {
+ prevComponent.getContainer().addVisibleComponent(selectedComponent, -1);
+ } else {
+ form.addVisibleComponent(selectedComponent, index - 2);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ } else if (event.getNativeKeyCode() == KeyCodes.KEY_T && !palettePanel.isTextboxFocused() && isActiveEditor()) {
+ SourceStructureBox.getSourceStructureBox().getSourceStructureExplorer().getTree().setFocus(true);
+ } else if (event.getNativeKeyCode() == KeyCodes.KEY_V && !palettePanel.isTextboxFocused() && isActiveEditor()) {
+ getVisibleComponentsPanel().focusCheckbox();
+ } else if (event.getNativeKeyCode() == KeyCodes.KEY_P && !palettePanel.isTextboxFocused() && isActiveEditor()) {
+ PropertiesBox.getPropertiesBox().getElement().getElementsByTagName("a").getItem(0).focus();
+ } else if (event.getNativeKeyCode() == KeyCodes.KEY_M && !palettePanel.isTextboxFocused() && isActiveEditor()) {
+ AssetListBox.getAssetListBox().getAssetList().getTree().setFocus(true);
+ }
+ }
+ }, KeyDownEvent.getType());
+ }
+
@SuppressWarnings("checkstyle:LineLength")
private native void registerNativeListeners()/*-{
var editor = this;
diff --git a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/actions/RefreshCompanionAction.java b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/actions/RefreshCompanionAction.java
index 36869878112..4aab313fe5a 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/actions/RefreshCompanionAction.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/actions/RefreshCompanionAction.java
@@ -6,13 +6,35 @@
package com.google.appinventor.client.editor.youngandroid.actions;
import com.google.appinventor.client.Ode;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.Event;
public class RefreshCompanionAction implements Command {
+
+ public RefreshCompanionAction() {
+ shortcutKeyHandler();
+ }
+
@Override
public void execute() {
if (Ode.getInstance().okToConnect()) {
Ode.getInstance().getTopToolbar().replUpdate();
}
}
+
+ private void shortcutKeyHandler() {
+ Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
+ @Override
+ public void onPreviewNativeEvent(Event.NativePreviewEvent event) {
+ NativeEvent nativeEvent = event.getNativeEvent();
+ if (event.getTypeInt() == Event.ONKEYDOWN && nativeEvent.getKeyCode() == KeyCodes.KEY_R
+ && nativeEvent.getAltKey()) {
+ nativeEvent.preventDefault();
+ execute();
+ }
+ }
+ });
+ }
}
diff --git a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/actions/ResetAction.java b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/actions/ResetAction.java
index 239ed04e50e..d97da5a5d89 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/actions/ResetAction.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/actions/ResetAction.java
@@ -7,13 +7,35 @@
package com.google.appinventor.client.editor.youngandroid.actions;
import com.google.appinventor.client.Ode;
+import com.google.gwt.dom.client.NativeEvent;
+import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.Command;
+import com.google.gwt.user.client.Event;
public class ResetAction implements Command {
+
+ public ResetAction() {
+ shortcutKeyHandler();
+ }
+
@Override
public void execute() {
if (Ode.getInstance().okToConnect()) {
Ode.getInstance().getTopToolbar().startRepl(false, false, false, false); // We are really stopping the repl here
}
}
+
+ private void shortcutKeyHandler() {
+ Event.addNativePreviewHandler(new Event.NativePreviewHandler() {
+ @Override
+ public void onPreviewNativeEvent(Event.NativePreviewEvent event) {
+ NativeEvent nativeEvent = event.getNativeEvent();
+ if (event.getTypeInt() == Event.ONKEYDOWN && nativeEvent.getKeyCode() == KeyCodes.KEY_R
+ && nativeEvent.getAltKey() && nativeEvent.getShiftKey()) {
+ execute();
+ nativeEvent.preventDefault();
+ }
+ }
+ });
+ }
}
diff --git a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/palette/YoungAndroidPalettePanel.java b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/palette/YoungAndroidPalettePanel.java
index b283f9085f4..ce61f3d3b2a 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/palette/YoungAndroidPalettePanel.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/palette/YoungAndroidPalettePanel.java
@@ -6,6 +6,7 @@
package com.google.appinventor.client.editor.youngandroid.palette;
+import com.google.appinventor.client.Ode;
import com.google.appinventor.client.editor.simple.components.i18n.ComponentTranslationTable;
import com.google.appinventor.client.editor.simple.SimpleComponentDatabase;
import com.google.appinventor.client.editor.simple.components.MockComponent;
@@ -15,6 +16,7 @@
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.DesignToolbar;
import com.google.appinventor.client.editor.youngandroid.YaFormEditor;
import com.google.appinventor.client.explorer.project.ComponentDatabaseChangeListener;
import com.google.appinventor.client.wizards.ComponentImportWizard;
@@ -31,6 +33,7 @@
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.RootPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.event.dom.client.KeyPressEvent;
@@ -44,12 +47,12 @@
import jsinterop.annotations.JsOverlay;
import jsinterop.annotations.JsType;
-import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.*;
+import java.util.Iterator;
+import java.util.Set;
import static com.google.appinventor.client.Ode.MESSAGES;
@@ -192,6 +195,21 @@ public void onChange(ChangeEvent event) {
}
});
+ /* User presses the slash key, the search text box is focused */
+ RootPanel.get().addDomHandler(new KeyDownHandler() {
+ @Override
+ public void onKeyDown(KeyDownEvent event) {
+ DesignToolbar designToolbar = Ode.getInstance().getDesignToolbar();
+ if (designToolbar.currentView == DesignToolbar.View.FORM && event.getNativeKeyCode() == 191
+ && !isTextboxFocused() && !event.isAltKeyDown()) {
+ {
+ event.preventDefault();
+ searchText.setFocus(true);
+ }
+ }
+ }
+ }, KeyDownEvent.getType());
+
panel.setSpacing(3);
panel.add(searchText);
panel.setWidth("100%");
@@ -504,4 +522,8 @@ public void reloadComponents() {
loadComponents();
}
+ public native boolean isTextboxFocused()/*-{
+ var element = $doc.activeElement;
+ return element.tagName === 'INPUT' && element.type === 'text' || element.tagName === 'TEXTAREA';
+ }-*/;
}
diff --git a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/properties/YoungAndroidLengthPropertyEditor.java b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/properties/YoungAndroidLengthPropertyEditor.java
index 1745fb951b8..65d98a312db 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/properties/YoungAndroidLengthPropertyEditor.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/editor/youngandroid/properties/YoungAndroidLengthPropertyEditor.java
@@ -140,6 +140,12 @@ public void onClick(ClickEvent event) {
initAdditionalChoicePanel(panel);
}
+ @Override
+ protected void openAdditionalChoiceDialog() {
+ super.openAdditionalChoiceDialog();
+ automaticRadioButton.setFocus(true);
+ }
+
@Override
protected void updateValue() {
super.updateValue();
diff --git a/appinventor/appengine/src/com/google/appinventor/client/explorer/SourceStructureExplorer.java b/appinventor/appengine/src/com/google/appinventor/client/explorer/SourceStructureExplorer.java
index 65bd2b32288..d9373f489a9 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/explorer/SourceStructureExplorer.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/explorer/SourceStructureExplorer.java
@@ -9,8 +9,14 @@
import com.google.appinventor.client.Ode;
import com.google.appinventor.client.widgets.TextButton;
import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
+import com.google.gwt.event.dom.client.MouseUpEvent;
+import com.google.gwt.event.dom.client.MouseUpHandler;
+import com.google.gwt.event.dom.client.BlurEvent;
+import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.logical.shared.CloseHandler;
@@ -130,9 +136,30 @@ public void onKeyDown(KeyDownEvent event) {
if (keyCode == KeyCodes.KEY_DELETE || keyCode == KeyCodes.KEY_BACKSPACE) {
event.preventDefault();
deleteItemFromTree();
+ } else if (event.isAltKeyDown() && keyCode == KeyCodes.KEY_N) {
+ event.preventDefault();
+ renameItem();
}
}
});
+ tree.addFocusHandler(new FocusHandler() {
+ @Override
+ public void onFocus(FocusEvent event) {
+ tree.getParent().setStyleName("gwt-Tree-focused");
+ }
+ });
+ tree.addBlurHandler(new BlurHandler() {
+ @Override
+ public void onBlur(BlurEvent event) {
+ tree.getParent().removeStyleName("gwt-Tree-focused");
+ }
+ });
+ tree.addMouseUpHandler(new MouseUpHandler() {
+ @Override
+ public void onMouseUp(MouseUpEvent event) {
+ tree.setFocus(true);
+ }
+ });
// Put a ScrollPanel around the tree.
ScrollPanel scrollPanel = new ScrollPanel(tree);
@@ -147,14 +174,7 @@ public void onKeyDown(KeyDownEvent event) {
renameButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
- TreeItem treeItem = tree.getSelectedItem();
- if (treeItem != null) {
- Object userObject = treeItem.getUserObject();
- if (userObject instanceof SourceStructureExplorerItem) {
- SourceStructureExplorerItem item = (SourceStructureExplorerItem) userObject;
- item.rename();
- }
- }
+ renameItem();
}
});
buttonPanel.add(renameButton);
@@ -194,6 +214,17 @@ private void deleteItemFromTree() {
}
}
+ private void renameItem() {
+ TreeItem treeItem = tree.getSelectedItem();
+ if (treeItem != null) {
+ Object userObject = treeItem.getUserObject();
+ if (userObject instanceof SourceStructureExplorerItem) {
+ SourceStructureExplorerItem item = (SourceStructureExplorerItem) userObject;
+ item.rename();
+ }
+ }
+ }
+
private void enableButtons(SourceStructureExplorerItem item) {
renameButton.setEnabled(item.canRename());
deleteButton.setEnabled(item.canDelete());
@@ -314,4 +345,8 @@ public void selectItem(SourceStructureExplorerItem item) {
public void unselectItem(SourceStructureExplorerItem item) {
selectItem(item, false);
}
+
+ public Tree getTree() {
+ return tree;
+ }
}
diff --git a/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/AddFormCommand.java b/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/AddFormCommand.java
index 15aff037a04..386156e85b9 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/AddFormCommand.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/AddFormCommand.java
@@ -25,8 +25,8 @@
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
@@ -109,9 +109,9 @@ private class NewFormDialog extends DialogBox {
newNameTextBox = new LabeledTextBox(MESSAGES.formNameLabel());
newNameTextBox.setText(defaultFormName);
- newNameTextBox.getTextBox().addKeyUpHandler(new KeyUpHandler() {
+ newNameTextBox.getTextBox().addKeyDownHandler(new KeyDownHandler() {
@Override
- public void onKeyUp(KeyUpEvent event) {
+ public void onKeyDown(KeyDownEvent event) {
int keyCode = event.getNativeKeyCode();
if (keyCode == KeyCodes.KEY_ENTER) {
handleOkClick(projectRootNode);
diff --git a/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/CopyYoungAndroidProjectCommand.java b/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/CopyYoungAndroidProjectCommand.java
index d865352e557..444bdd0626b 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/CopyYoungAndroidProjectCommand.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/CopyYoungAndroidProjectCommand.java
@@ -20,8 +20,8 @@
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
-import com.google.gwt.event.dom.client.KeyUpEvent;
-import com.google.gwt.event.dom.client.KeyUpHandler;
+import com.google.gwt.event.dom.client.KeyDownEvent;
+import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
@@ -154,9 +154,9 @@ public String getErrorMessage() {
}
});
newNameTextBox.setText(defaultNewName);
- newNameTextBox.getTextBox().addKeyUpHandler(new KeyUpHandler() {
+ newNameTextBox.getTextBox().addKeyDownHandler(new KeyDownHandler() {
@Override
- public void onKeyUp(KeyUpEvent event) {
+ public void onKeyDown(KeyDownEvent event) {
int keyCode = event.getNativeKeyCode();
if (keyCode == KeyCodes.KEY_ENTER) {
handleOkClick(oldProjectNode);
diff --git a/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/DeleteFileCommand.java b/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/DeleteFileCommand.java
index 9dc7d2518ef..190057aa4f5 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/DeleteFileCommand.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/explorer/commands/DeleteFileCommand.java
@@ -22,6 +22,9 @@
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.FocusEvent;
+import com.google.gwt.event.dom.client.FocusHandler;
+import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Window;
@@ -100,7 +103,8 @@ private class DeleteFormDialog extends DialogBox {
private final String formName;
DeleteFormDialog(final YoungAndroidSourceNode node) {
- super(false, true);
+ super(false, false);
+ setGlassEnabled(true);
this.node = node;
formName = node.getFormName();
@@ -108,6 +112,11 @@ private class DeleteFormDialog extends DialogBox {
setStylePrimaryName("ode-DialogBox");
setText(MESSAGES.removeFormButton());
+ Button topInvisible = new Button();
+ Button bottomInvisible = new Button();
+ topInvisible.setStyleName("FocusTrap");
+ bottomInvisible.setStyleName("FocusTrap");
+
Button cancelButton = new Button(MESSAGES.cancelButton());
cancelButton.addClickHandler(new ClickHandler() {
@Override
@@ -133,11 +142,13 @@ public void onClick(ClickEvent event) {
labelPanel.add(warnmsg);
labelPanel.setSize("100%", "22px");
contentPanel.add(labelPanel);
+ contentPanel.add(topInvisible);
contentPanel.add(nameTextBox);
HorizontalPanel buttonPanel = new HorizontalPanel();
HorizontalPanel checkboxPanel = new HorizontalPanel();
buttonPanel.add(cancelButton);
buttonPanel.add(deleteButton);
+ buttonPanel.add(bottomInvisible);
checkboxPanel.add(cb);
checkboxPanel.setSize("100%", "20px");
contentPanel.add(checkboxPanel);
@@ -148,15 +159,32 @@ public void onClick(ClickEvent event) {
nameTextBox.getTextBox().addKeyUpHandler(new KeyUpHandler() {
@Override
public void onKeyUp(KeyUpEvent event) {
+ if (event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) {
+ hide();
+ executionFailedOrCanceled();
+ }
if (nameTextBox.getText().equals(formName)) {
deleteButton.setEnabled(true);
nameTextBox.setColor("#00c8ff");
+ if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
+ handleOkClick();
+ }
} else {
deleteButton.setEnabled(false);
nameTextBox.setColor("red");
}
}
});
+ topInvisible.addFocusHandler(new FocusHandler() {
+ public void onFocus(FocusEvent event) {
+ cancelButton.setFocus(true);
+ }
+ });
+ bottomInvisible.addFocusHandler(new FocusHandler() {
+ public void onFocus(FocusEvent event) {
+ nameTextBox.setFocus(true);
+ }
+ });
add(contentPanel);
}
diff --git a/appinventor/appengine/src/com/google/appinventor/client/explorer/dialogs/NoProjectDialogBox.java b/appinventor/appengine/src/com/google/appinventor/client/explorer/dialogs/NoProjectDialogBox.java
index 3c03a337531..89d80708a2b 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/explorer/dialogs/NoProjectDialogBox.java
+++ b/appinventor/appengine/src/com/google/appinventor/client/explorer/dialogs/NoProjectDialogBox.java
@@ -12,6 +12,7 @@
import com.google.appinventor.client.wizards.youngandroid.NewYoungAndroidProjectWizard;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
@@ -54,6 +55,10 @@ public void execute(Project project) {
Button goToYR;
@UiField
Button noDialogNewProject;
+ @UiField
+ Button topInvisible;
+ @UiField
+ Button bottomInvisible;
/**
* Creates a new dialog box when the user has no current projects in their
@@ -66,6 +71,8 @@ public NoProjectDialogBox() {
this.center();
this.setAnimationEnabled(true);
this.setAutoHideEnabled(true);
+ this.setModal(false);
+ noDialogNewProject.setFocus(true);
lastDialog = this;
}
@@ -109,4 +116,14 @@ public static void closeIfOpen() {
lastDialog = null;
}
}
+
+ @UiHandler("topInvisible")
+ protected void FocusLast(FocusEvent event) {
+ closeDialogBox.setFocus(true);
+ }
+
+ @UiHandler("bottomInvisible")
+ protected void FocusFirst(FocusEvent event) {
+ goToPurr.setFocus(true);
+ }
}
diff --git a/appinventor/appengine/src/com/google/appinventor/client/explorer/dialogs/NoProjectDialogBox.ui.xml b/appinventor/appengine/src/com/google/appinventor/client/explorer/dialogs/NoProjectDialogBox.ui.xml
index 6b414d3744e..862747c0faf 100644
--- a/appinventor/appengine/src/com/google/appinventor/client/explorer/dialogs/NoProjectDialogBox.ui.xml
+++ b/appinventor/appengine/src/com/google/appinventor/client/explorer/dialogs/NoProjectDialogBox.ui.xml
@@ -13,6 +13,7 @@
+