Commit 30355198 authored by Evan W. Patton's avatar Evan W. Patton Committed by Jeffrey Schiller

Add touch handling for component helper widgets (#1251)

Implementation of the drag and drop support for the designer did not
handle touch events on the help and remove extension buttons in the
palette. This commit adds the corresponding implementations to improve
touch support.

Change-Id: I7a877683da6421c67104f4fb704e7c35fd90f578
parent 2db96fcc
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2018 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.simple.palette;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.TouchEndEvent;
import com.google.gwt.event.dom.client.TouchEndHandler;
import com.google.gwt.event.dom.client.TouchStartEvent;
import com.google.gwt.event.dom.client.TouchStartHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.Image;
/**
* AbstractPaletteItemWidget provides a common superclass for buttons presented in the
* {@link SimplePaletteItem} for a component.
*/
public abstract class AbstractPaletteItemWidget extends Image {
protected final SimpleComponentDescriptor scd;
AbstractPaletteItemWidget(SimpleComponentDescriptor scd, ImageResource image) {
this.scd = scd;
AbstractImagePrototype.create(image).applyTo(this);
this.addStyleName("ode-SimplePaletteItem-button");
addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
handleClick();
}
});
addTouchStartHandler(new TouchStartHandler() {
@Override
public void onTouchStart(TouchStartEvent touchStartEvent) {
// Otherwise captured by SimplePaletteItem
touchStartEvent.stopPropagation();
}
});
addTouchEndHandler(new TouchEndHandler() {
@Override
public void onTouchEnd(TouchEndEvent touchEndEvent) {
handleClick();
}
});
}
/**
* Handles when the user clicks (or taps) on the button.
*/
protected abstract void handleClick();
}
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2009-2011 Google, All Rights reserved
// Copyright 2011-2012 MIT, All rights reserved
// Copyright 2011-2018 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.simple.palette;
import com.google.appinventor.client.Images;
import com.google.appinventor.client.Ode;
import static com.google.appinventor.client.Ode.MESSAGES;
import com.google.appinventor.client.ComponentsTranslation;
import com.google.appinventor.client.Ode;
import com.google.appinventor.client.utils.PZAwarePositionCallback;
import com.google.common.base.Strings;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupListener;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import static com.google.appinventor.client.Ode.MESSAGES;
/**
* Defines a widget that has the appearance of a question mark and
* creates a popup with information about a component when it is clicked on.
*
*/
public final class ComponentHelpWidget extends Image {
private static ImageResource imageResource = null;
public final class ComponentHelpWidget extends AbstractPaletteItemWidget {
private static final ImageResource imageResource = Ode.getImageBundle().help();
// Keep track of the last time (in milliseconds) of the last closure
// so we don't reopen a popup too soon after closing it. Specifically,
......@@ -41,8 +37,7 @@ public final class ComponentHelpWidget extends Image {
private class ComponentHelpPopup extends PopupPanel {
private ComponentHelpPopup(final SimpleComponentDescriptor scd,
final Widget sender) {
private ComponentHelpPopup() {
// Create popup panel.
super(true);
setStyleName("ode-ComponentHelpPopup");
......@@ -108,16 +103,16 @@ public final class ComponentHelpWidget extends Image {
// When the panel is closed, save the time in milliseconds.
// This will help us avoid immediately reopening it if the user
// closed it by clicking on the question-mark icon.
addPopupListener(new PopupListener() {
addCloseHandler(new CloseHandler<PopupPanel>() {
@Override
public void onPopupClosed(PopupPanel sender, boolean autoClosed) {
public void onClose(CloseEvent<PopupPanel> event) {
lastClosureTime = System.currentTimeMillis();
}
});
// Use a Pinch Zoom aware PopupPanel.PositionCallback to handle positioning to
// avoid the Google Chrome Pinch Zoom bug.
setPopupPositionAndShow(new PZAwarePositionCallback(sender.getElement()) {
setPopupPositionAndShow(new PZAwarePositionCallback(ComponentHelpWidget.this.getElement()) {
@Override
public void setPosition(int offsetWidth, int offsetHeight) {
// Position the upper-left of the panel just to the right of the
......@@ -130,8 +125,8 @@ public final class ComponentHelpWidget extends Image {
Math.max(0, Window.getClientHeight()
- offsetHeight + Y_OFFSET)));
} else {
setPopupPosition(sender.getAbsoluteLeft() + X_OFFSET,
Math.min(sender.getAbsoluteTop() + Y_OFFSET,
setPopupPosition(ComponentHelpWidget.this.getAbsoluteLeft() + X_OFFSET,
Math.min(ComponentHelpWidget.this.getAbsoluteTop() + Y_OFFSET,
Math.max(0, Window.getClientHeight()
- offsetHeight + Y_OFFSET)));
}
......@@ -141,22 +136,16 @@ public final class ComponentHelpWidget extends Image {
}
public ComponentHelpWidget(final SimpleComponentDescriptor scd) {
if (imageResource == null) {
Images images = Ode.getImageBundle();
imageResource = images.help();
}
AbstractImagePrototype.create(imageResource).applyTo(this);
addClickListener(new ClickListener() {
@Override
public void onClick(Widget sender) {
final long MINIMUM_MS_BETWEEN_SHOWS = 250; // .25 seconds
super(scd, imageResource);
}
if (System.currentTimeMillis() - lastClosureTime >=
MINIMUM_MS_BETWEEN_SHOWS) {
new ComponentHelpPopup(scd, sender);
}
}
}
);
@Override
protected void handleClick() {
final long MINIMUM_MS_BETWEEN_SHOWS = 250; // .25 seconds
if (System.currentTimeMillis() - lastClosureTime >=
MINIMUM_MS_BETWEEN_SHOWS) {
new ComponentHelpPopup();
}
}
}
// -*- mode: java; c-basic-offset: 2; -*-
// Copyright 2015-2016 MIT, All rights reserved
// Copyright 2015-2018 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.simple.palette;
import com.google.appinventor.client.Images;
import com.google.appinventor.client.Ode;
import com.google.appinventor.client.editor.simple.SimpleComponentDatabase;
import com.google.appinventor.client.editor.youngandroid.YaBlocksEditor;
import com.google.appinventor.client.editor.youngandroid.YaProjectEditor;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;
import static com.google.appinventor.client.Ode.MESSAGES;
......@@ -23,32 +17,23 @@ import static com.google.appinventor.client.Ode.MESSAGES;
* Defines a widget that has the appearance of a red close button.
* The Widget is clicked to delete the associated component
*/
public class ComponentRemoveWidget extends Image {
private static ImageResource imageResource = null;
public class ComponentRemoveWidget extends AbstractPaletteItemWidget {
private static final ImageResource imageResource = Ode.getImageBundle().deleteComponent();
private static Ode ode = Ode.getInstance();
private final SimpleComponentDescriptor scd;
private static final Ode ode = Ode.getInstance();
public ComponentRemoveWidget(SimpleComponentDescriptor simpleComponentDescriptor) {
if (imageResource == null) {
Images images = Ode.getImageBundle();
imageResource = images.deleteComponent();
}
this.scd = simpleComponentDescriptor;
AbstractImagePrototype.create(imageResource).applyTo(this);
addClickListener(new ClickListener() {
super(simpleComponentDescriptor, imageResource);
}
@Override
public void onClick(Widget widget) {
if (Window.confirm(MESSAGES.reallyRemoveComponent())) {
long projectId = ode.getCurrentYoungAndroidProjectId();
YaProjectEditor projectEditor = (YaProjectEditor) ode.getEditorManager().getOpenProjectEditor(projectId);
SimpleComponentDatabase componentDatabase = SimpleComponentDatabase.getInstance();
componentDatabase.addComponentDatabaseListener(projectEditor);
componentDatabase.removeComponent(scd.getName());
}
}
});
@Override
protected void handleClick() {
if (Window.confirm(MESSAGES.reallyRemoveComponent())) {
long projectId = ode.getCurrentYoungAndroidProjectId();
YaProjectEditor projectEditor = (YaProjectEditor) ode.getEditorManager().getOpenProjectEditor(projectId);
SimpleComponentDatabase componentDatabase = SimpleComponentDatabase.getInstance();
componentDatabase.addComponentDatabaseListener(projectEditor);
componentDatabase.removeComponent(scd.getName());
}
}
}
......@@ -69,13 +69,11 @@ public class SimplePaletteItem extends DragSourcePanel {
HorizontalPanel optPanel = new HorizontalPanel();
ComponentHelpWidget helpImage = new ComponentHelpWidget(scd);
helpImage.addStyleName("ode-SimplePalleteItem-button");
optPanel.add(helpImage);
optPanel.setCellHorizontalAlignment(helpImage, HorizontalPanel.ALIGN_LEFT);
if (scd.getExternal()) {
ComponentRemoveWidget deleteImage = new ComponentRemoveWidget(scd);
deleteImage.addStyleName("ode-SimplePalleteItem-button");
optPanel.add(deleteImage);
optPanel.setCellHorizontalAlignment(deleteImage, HorizontalPanel.ALIGN_RIGHT);
}
......
......@@ -825,7 +825,7 @@ select {
color: #555;
}
.ode-SimplePalleteItem-button {
.ode-SimplePaletteItem-button {
padding: 2px;
}
......
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