Dialog causes drag done events to not propagate - gluon-mobile

I'm using a popup dialog during a drag and drop operation. When the drop happens a dialog pops up and when it is dismissed the event chain should continue and allow something to happen when the drag operation ends. If the popup dialog is FX then there is no problem but if it's Gluon the drag done operation doesn't happen.
Here is a sample code:
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.DataFormat;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.Background;
import javafx.scene.layout.BackgroundFill;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import com.gluonhq.charm.glisten.mvc.View;
public class MainView extends View {
HBox root;
public MainView(String name) {
super(name);
Label source = new Label("Source");
configureDragSource(source);
Label target = new Label("Target");
configureDragTarget(target);
Label popupTarget = new Label("Popup Target");
configureDragPopupTarget(popupTarget);
root = new HBox(40, source, target, popupTarget);
setCenter(root);
}
private void configureDragSource(Label source) {
source.setOnDragDetected(e -> {
root.setBackground(new Background(new BackgroundFill(Color.RED, null, null)));
Dragboard db = source.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
content.put(DataFormat.PLAIN_TEXT, source.getText());
db.setContent(content);
});
source.setOnDragDone(e -> root.setBackground(new Background(new BackgroundFill(null, null, null))));
}
private void configureDragTarget(Label target) {
target.setOnDragOver(e -> e.acceptTransferModes(TransferMode.ANY));
}
private void configureDragPopupTarget(Label popupTarget) {
popupTarget.setOnDragOver(e -> e.acceptTransferModes(TransferMode.ANY));
popupTarget.setOnDragDropped(e -> {
javafx.scene.control.Alert popup1 = new javafx.scene.control.Alert(AlertType.INFORMATION);
com.gluonhq.charm.glisten.control.Alert popup2 = new com.gluonhq.charm.glisten.control.Alert(AlertType.INFORMATION);
popup1.showAndWait();
});
}
}
The source should be dragged upon which the background changes to red. When the drag operation is done the backgrounds should return to default. The regular drop target does nothing and the color change works. But when dropping on the popup target the dialog appears and when it is closed the color changes only for the FX dialog and not for the gluon dialog. Change popup1.showAndWait(); to popup2.
If important this is the application class
import com.gluonhq.charm.glisten.application.MobileApplication;
public class TestApplication extends MobileApplication {
#Override
public void init() {
addViewFactory(HOME_VIEW, () -> new MainView(HOME_VIEW));
}
public static void main(String[] args) {
launch(args);
}
}
and this is the gradle build file:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.3.5'
}
}
apply plugin: 'org.javafxports.jfxmobile'
apply plugin: 'eclipse'
jar {
manifest {
attributes 'Main-Class': 'com.test.TestApplication'
}
}
jfxmobile {
downConfig {
version = '3.3.0'
plugins 'display', 'lifecycle', 'statusbar', 'storage'
}
android {
compileSdkVersion = 19
// manifest = 'src/android/AndroidManifest.xml'
}
ios {
infoPList = file('src/ios/Default-Info.plist')
forceLinkClasses = [
'com.gluonhq.**.*',
'javax.annotations.**.*',
'javax.inject.**.*',
'javax.json.**.*',
'org.glassfish.json.**.*'
]
}
}
eclipse {
classpath {
downloadJavadoc = true
downloadSources = true
}
}
repositories {
jcenter()
maven {
url 'http://nexus.gluonhq.com/nexus/content/repositories/releases'
}
}
mainClassName = 'com.test.TestApplication'
dependencies {
compile 'com.gluonhq:charm:4.3.5'
}
task wrapper(type: Wrapper) {
gradleVersion = '4.2'
}
Happens also on compile 'com.gluonhq:charm:4.3.7' and 4.4.0.
Running on Java 8 b141. Why does this happen? Is this a bug?

JavaFX built-in dialogs and Gluon Dialogs are not the same. In fact, the latter extends from Layer, while being modal and blocking, like the former.
Running on Mac the posted code, I get a NPE after dropping over popupTarget, that can be easily solved using:
Platform.runLater(() -> popup2.showAndWait());
Also, given that the drag event is consumed by the dialog, a possible solution could be:
Platform.runLater(() ->
popup2.showAndWait()
.ifPresent(r ->
root.setBackground(new Background(new BackgroundFill(null, null, null)))));
So you could refactor the setOnDragDone method, and just create a method that could be called after the dialog is closed as well.
EDIT
These are the drag events that both target and source receive once the dnd event has started:
The target receives these events on a drag and drop gesture:
DRAG_OVER
DRAG_OVER
... // until drop is done:
// show Dialog
...
// hide Dialog
DRAG_DROPPED
DRAG_EXITED
DRAG_EXITED_TARGET
those work exactly the same with JavaFX and Gluon dialogs (at least on Windows. On Mac because of the NPE, using Platform.runLater() delays obviously the show Dialog and hide Dialog events, but lets just focus on Windows for now).
Right after that last event, the source receives:
DRAG_DONE
but only with a JavaFX dialog.
After some debugging, the reason why the Gluon's Dialog aborts the drag done event can be explained as follows:
The Scene class has a DnDGesture private class:
/**
* A Drag and Drop gesture has a lifespan that lasts from mouse
* PRESSED event to mouse RELEASED event.
*/
class DnDGesture {
...
}
And as it is explained in the comment, it has a lifespan from mouse pressed event to mouse release event.
Using JavaFX built-in dialog, this is displayed in a new Stage and therefore a new Scene. The key here is that this dialog (and all the set of mouse events) is displayed in a new modal stage, so once the dialog is hidden, the primary stage takes the focus again and resumes, finishing properly the dnd gesture as the mouse is released.
But using Gluon's dialog, there is no second stage. Everything happens in the same stage, and once the mouse is released, the Scene.DnDGesture becomes null, so when the DRAG_EXITED_TARGET event happens in the target, the proper call is done to finish the dnd process, but at this point dndGesture is null, and that call doesn't reach the source anymore.
I don't consider this a bug, but more like a tradeoff, as there are a number of reasons to avoid a second stage/scene on a mobile environment and keep the View/Layer (in one single stage) design.

Related

Open a Modal Dialog when issue is Done

I’m just starting with Forge and JIRA apps development, I need to open a ModalDialog when an issue changes its state to “Done” (either by dragging it to the Done column or by changing its status in the issue panel). I don’t know where to start, I tried clonning the jira-issue-activity-ui-kit starter but I don’t get where the modal should open, any ideas? Thanks
This is the code I've tried:
const DONE = 'Done';
export async function run(event, context) {
console.log('Hello World!', event, event.changelog.items);
// if the issue is solved (status changed to Done)
if (event.changelog.items.some(function changedToPreferredStatus(change) {
return statusChangedTo(change, DONE);
})) {
let description = event.issue.fields.summary;
// OPEN MODAL DIALOG HERE
}
}
function statusChangedTo(change, to) {
return change.field === 'status' && change.toString === to;
}

Vaadin Loading Spinner

Looking for a way to add a Loading Spinner as gif into my Vaadin 14 App. I only find a solution where i can create a "curtain" which is a layover over the screen. But dont get it done to add a gif which is spinning while loading. Does anyone have this already got to work?
Its so easy to change the color:
just add
.v-loading-indicator {
background-color: blue !important;
}
to the main.css
If you have a Vaadin Flow app, you can add an Image for the gif, and then remove it once the loading is complete.
Since it sounds like you are doing long-running tasks on the backend, you will probably want to use #Push in the application so you can notify the browser when the work is complete.
UI ui = UI.getCurrent(); // get the instance before running a new thread
backendService.longRunningTask()
.addCallback(
new ListenableFutureCallback<>() {
#Override
public void onFailure(Throwable ex) {
ui.access(
() -> {
// setup for error
spinner.setVisible(false);
}
);
}
#Override
public void onSuccess(Void result) {
ui.access(
() -> {
// setup for task completed
spinner.setVisible(false);
}
);
}
}
);
See this Vaadin Cookbook example for a complete example https://cookbook.vaadin.com/long-running-task

Disable window offset when keyboard appears for ios app

Disable window offset when keyboard appears for ios app
I would like to disable the window offset when the keyboard appears for the ios app. For an android app, this is done via AndroidManifest.xml:
<activity ... android:windowSoftInputMode="adjustResize">
When the keyboard appears, the components do not move from their places.
Is it possible to get this behavior for ios?
Found the solution here in the comments:
iOS Make window-scrolling optional for Items
https://bugreports.qt.io/browse/QTBUG-80790
(this workaround works well for me)
========================
Adrian Eddy added a comment - 11 Apr '20 01:44 - edited
I found a workaround that works with QML . The idea is to install an event filter on QQuickItem and listen for a QEvent::InputMethodQuery with Qt::InputMethodQuery::ImCursorRectangle. Then we set its value to empty QRectF and Qt will no longer scroll the view to show that text field.
in C++ prepare a class and expose it to QML:
class Api : public QObject {
Q_OBJECT
....
public:
Q_INVOKABLE void setupImEventFilter(QQuickItem *item) {
static thread_local ImFixer imf;
item->installEventFilter(&imf);
}
}
// somewhere in main():
view.rootContext()->setContextProperty("api", new Api());
We'll need the actual event filter too:
class ImFixer :
public QObject {
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event) override {
if (event->type() == QEvent::InputMethodQuery) {
QInputMethodQueryEvent *imEvt = static_cast<QInputMethodQueryEvent *>(event);
if (imEvt->queries() == Qt::InputMethodQuery::ImCursorRectangle) {
imEvt->setValue(Qt::InputMethodQuery::ImCursorRectangle, QRectF());
return true;
}
}
return QObject::eventFilter(obj, event);
}
};
Finally in QML add:
TextField {
id: tf;
...
Component.onCompleted: api.setupImEventFilter(tf);
}

GWT Window.confirm() triggered by onchange of ValueListBox crashing Safari on iPad iOS 7.0.6

I recently received a support ticket that some of our web app's functionality is crashing safari on the iPad. This functionality had no problems prior to the latest iOS 7.0.6 update. We have a few GWT ValueListBoxes that change the DOM when their values are changed. Prior to making the changes, we present the user with a Window.confirm() message to inform them of the effects the changes will have and ask whether or not they would still like to proceed. Since the update, the confirm choices do nothing and Safari crashes. This is only happening on the iPad. The functionality works fine on the desktop browsers (IE, Chrome, Firefox, Safari and the Chrome mobile emulator), but crashes safari on the iPad. Is anyone else having this issue?
Here's a screenshot of the crash:
And here's a sample of the code:
this._view.isPrimaryFoodGen().addValueChangeHandler(new ValueChangeHandler<Boolean>()
{
#Override
public void onValueChange(final ValueChangeEvent<Boolean> event)
{
#SuppressWarnings("unchecked")
ValueListBoxWithOldValue<Boolean> vlb = (ValueListBoxWithOldValue<Boolean>)event.getSource();
if (confirmQuestionChange() ){
changeGroupAndQuestions(CONSTANTS.PRIMARY_FOOD, event.getValue());
}
else {
vlb.setValue(vlb.getOldValue());
}
}
});
public boolean confirmQuestionChange()
{
if (!this._view.isImageCriteriaQuestionsVisible())
{ //questions aren't currently visible
return true;
}
boolean confirmed = Window.confirm("Changing this response will delete image data already collected. Do you wish to proceed?");
return confirmed;
}
Any help on a solution for preventing the crash on the iPad would be greatly appreciated. I have tried focusing on another element prior to calling Window.confirm() in hopes that the overlay and the ValueListBox choices would be removed to stop any JS conflicts, but it hasn't worked.
Am I at the mercy of Apple until the next update fixes this?
Or is there a viable solution?
OK, so it turns out that since I couldn't find a fix to continue using Window.confirm(), I had to implement a solution by changing the onValueChange() and confirmQuestionChange() methods to use a manually created DialogBox instead of Window.confirm(). It isn't the optimal solution, but Safari does not crash on the iPad anymore and users can get their work done. Here are the code changes:
this._view.isPrimaryFoodGen().addValueChangeHandler(new ValueChangeHandler<Boolean>()
{
#Override
public void onValueChange(final ValueChangeEvent<Boolean> event)
{
confirmQuestionChange(CONSTANTS.PRIMARY_FOOD, event);
}
});
public void confirmQuestionChange(final String question, ValueChangeEvent<Boolean> event)
{
final ValueListBoxWithOldValue<Boolean> vlb = (ValueListBoxWithOldValue<Boolean>)event.getSource();
if (!this._view.isImageCriteriaQuestionsVisible()) //questions aren't currently visible, can change them no problem
{
changeGroupAndQuestions(question, vlb.getValue());
}
else{
//the following fix was put in place for issues with Safari on the iPad OPS-76
final DialogBox dialogBox = new DialogBox();
dialogBox.setHTML("<center>Changing this response will delete<br />image data already collected.<br />Do you wish to proceed?</center>");
dialogBox.setAnimationEnabled(true);
Button yesButton = new Button("YES");
Button noButton = new Button("NO");
HorizontalPanel dialogHPanel = new HorizontalPanel();
dialogHPanel.setWidth("100%");
dialogHPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
dialogHPanel.add(noButton);
dialogHPanel.add(yesButton);
noButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
vlb.setValue(vlb.getOldValue());
dialogBox.hide();
}
});
yesButton.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
changeGroupAndQuestions(question, vlb.getValue());
dialogBox.hide();
}
});
// Set the contents of the Widget
dialogBox.setWidget(dialogHPanel);
dialogBox.setPopupPosition(180, 425);
dialogBox.show();
}
}
Here's a screenshot:
As you can see, the ValueListBox options close before the DialogBox appears and the screen no longer locks.

how to disable(Hide) application icon from SwitchApplication popup screen in blackberry?

i am developing an application which contain alternative entry point.
and i put tick mark in "Do not display in Blackberry Home screen". here it is working fine it does not show icon on the home screen. but my problem is that
when i am click on SwitchApplication from menu(Home screen), the alternative entry point icon is showing on the popup screen like following image. i dont want to show that icon.i want hide that icon programatically.
please help me
You can hide app if it's service. Set system module (systemmodule) to true for bb ant tools. There is similar options for JDE and Eclipse plugin.
just override this method into our application
like following
private static boolean flag=false;
public static void main(String[] args)
{
StartUp startUp;
if(args!=null && args.length>0 && args[0].equals("gui")){
flag=false;
startUp = new StartUp("gui");
startUp.enterEventDispatcher();
}else{
flag=true;
startUp = new StartUp();
startUp.enterEventDispatcher();
}
}
i override this method
protected boolean acceptsForeground() {
return flag;
}
This is the code that I ended up using that worked for me. I had tried putting the acceptsForeground in my main launcher class at first, but then put it in PushListener itself instead to prevent it from appearing in the running tasks menu. Worked fine.
Launcher Class
public static void main(String[] args) {
if (args != null && args.length > 0 && args[0].equals("gui")) {
MyApp app = new MyApp();
app.enterEventDispatcher();
} else {
PushListener.waitForInstance().start();
}
}
PushListener Class
protected boolean acceptsForeground() {
return false; // You could use a variable instead if you wanted.
}
It's quite simple if you use blackberry eclipse plugin.
open "blackberry_description_app.xml", just check this: Don't display the app icon on blackberry home screen.

Resources