Vaadin Loading Spinner - vaadin

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

Related

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.

Loading screen inside handleNavigationRequest in Browserfield Blackberry

Inside my application, I'm displaying a website using BrowserField. And when each link inside the site is selected, I need to show loading screen so that the user won't feel blank.
I was able to add the loading screen inside this method
public void documentCreated(BrowserField browserField,
ScriptEngine scriptEngine, Document document)
But the problem is only when connection is established, this method will be called and so there will be a delay before the loading screen is displayed.
So I tried implementing the ProtocolController and adding the loading screen inside this method
public void handleNavigationRequest(BrowserFieldRequest request)
But still, the loading screen is displayed after a small delay (same as when it was under documentCreated method)
This is my code snippet
public void handleNavigationRequest(BrowserFieldRequest request)
throws Exception {
if (!NetworkUtil.isNetworkAvailable()) {
Dialog.inform(Strings.NETWORK_ERROR);
} else {
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
BaseScreen.showLoadingProgress(Strings.LOADING);
}
});
InputConnection ic = handleResourceRequest(request);
browserField.displayContent(ic, request.getURL());
}
}
I tried this outside the thread as well....Still the same is happening. For testing, I added a dialog inside this method and it was coming on the same time I'm clicking any link inside the site. Only this loading screen takes time to load.
Is there any way to make this happen ?
Also, the browser field is taking a bit longer to load the website compared to the native browser.
Am I missing something here ! Please help
I have tried the documentUnloading method as you suggested. But it is not getting triggered. Given below is the code snippet, could you please check what I'm doing wrong here...!!
protected void onUiEngineAttached(boolean attached) {
if (attached) {
BaseScreen.showLoadingProgress(Strings.LOADING);
}
super.onUiEngineAttached(attached);
}
try {
listener = new BrowserFieldListener() {
// Page starts loading...
public void documentCreated(BrowserField browserField,
ScriptEngine scriptEngine, Document document)
{
// show the loading screen
//showLoadingProgress(Strings.LOADING);
}
public void documentError(BrowserField browserField,
Document document) {
hideLoadingProgress();
Dialog.inform(Strings.NETWORK_ERROR);
}
public void documentAborted(BrowserField browserField,
Document document) {
hideLoadingProgress();
Dialog.inform(Strings.NETWORK_ERROR);
}
public void documentUnloading(BrowserField browserField,
Document document) {
BaseScreen.showLoadingProgress(Strings.LOADING);
}
// Page loaded
public void documentLoaded(BrowserField browserField,
Document document) {
// the document has loaded, hide loading popup ...
BaseScreen.hideLoadingProgress();
}
};
} catch (Exception ex) {
Dialog.inform(Strings.NETWORK_ERROR);
}
browserField.addListener(listener);
// add the browser field to a ui manager or screen
add(browserField);
// request the content
browserField.requestContent(URL);
I do this using the BrowserFieldListener (see BrowserFieldListener.html). It is slightly counter intuitive, but I display the loading screen in documentUnloading(), and remove it in documentLoaded(). When I first populate the BrowserField I also push the loading screen, and when the screen with the BrowserField is closed, I make sure the loading screen is popped too. So not a pretty solution, but it works for me.
And yes, in general, the BrowserField is slower than the Browser. I have not found a way round it. However one significant aspect is caching. Look for information on creating your own cache for the BrowserField - there is Thread on here and a KB article on the BB Web site. Sorry can't find them atm, will update when I do.
Update
As found by the OP, the caching article is here.
Further Update
Just to clarify two things:
You must associate the Listener with the BrowserField, using the addListener method.
Assuming you do the usual requestContent() for the initial load of your BrowserField, you will need to push the loading screen yourself because the first method in listener that will be invoked (assuming it has worked of course), will be documentLoaded().
A sample demonstrating how to use the Listener is included here:
listener sample

Refresh Screen to Update ListField with new Data

I am using a ListField Control to display data returned from xml webservice. I want to refresh the ListField or the screen every minute to update the ListField with new records or data.
I tried using the code below but it is not working properly (It is hanging).
public MyApp() {
// Push a screen onto the UI stack for rendering.
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(new MyScreen());
}
},5000,true);
}
ResponseHandler handler = new ResponseHandler();
ListField listUsers = new ListField(handler.getItem().size());
public MyScreen() {
setTitle("yQAforum");
//Fetch the xml from the web service
String wsReturnString = GlobalV.Fetch_Webservice("myDs");
//Parse returned xml
SAXParserImpl saxparser = new SAXParserImpl();
ByteArrayInputStream stream = new ByteArrayInputStream(wsReturnString.getBytes());
try {
saxparser.parse( stream, handler );
}
catch ( Exception e ) {
response.setText( "Unable to parse response.");
}
//Return vector sze from the handler class
listUsers.setSize(handler.getItem().size());
listUsers.setCallback(this);
listUsers.setEmptyString("No Users found", 0);
add(listUsers);
}
You are attempting to fetch data from your webservice on the UI thread. That's almost always the wrong thing to do.
The UI thread (also known as the main thread) is responsible for drawing the UI, and tracking user actions, like touches, or navigation via a trackpad/trackball. If the UI thread is blocked waiting for a remote web server to respond, it cannot service the UI.
There's a couple changes you should make:
public MyApp() {
// Push a screen onto the UI stack for rendering.
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(new MyScreen());
}
},5000,true);
}
should be changed to
public MyApp() {
// Push a screen onto the UI stack for rendering.
pushScreen(new MyScreen());
}
The MyApp() constructor will already be called on the UI thread, so there is no need to use invokeLater() to perform the pushScreen() call on the UI thread. It already will be called on the UI thread, if run from within the MyApp constructor. Also, the 5000 msec delay isn't really helpful. This will just delay the startup of your app by 5 seconds, which users will hate.
If you are trying to implement a splash screen, or something similar, when the app starts up, please search stack overflow for "BlackBerry splash screen", and I'm sure you'll find results.
Now, once your MyScreen class is created, you should take care not to fetch web service results from the UI thread. The MyScreen constructor will be run on the UI thread. If you want, you can initiate a web service request on a background thread, once the screen is shown. One way to do that is to use onUiEngineAttached():
protected void onUiEngineAttached(boolean attached) {
if (attached) {
// TODO: you might want to show some sort of animated
// progress UI here, so the user knows you are fetching data
Timer timer = new Timer();
// schedule the web service task to run every minute
timer.schedule(new WebServiceTask(), 0, 60*1000);
}
}
public MyScreen() {
setTitle("yQAforum");
listUsers.setEmptyString("No Users found", 0);
listUsers.setCallback(this);
add(listUsers);
}
private class WebServiceTask extends TimerTask {
public void run() {
//Fetch the xml from the web service
String wsReturnString = GlobalV.Fetch_Webservice("myDs");
//Parse returned xml
SAXParserImpl saxparser = new SAXParserImpl();
ByteArrayInputStream stream = new ByteArrayInputStream(wsReturnString.getBytes());
try {
saxparser.parse( stream, handler );
}
catch ( Exception e ) {
response.setText( "Unable to parse response.");
}
// now, update the UI back on the UI thread:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
// TODO: record the currently selected, or focused, row
//Return vector sze from the handler class
listUsers.setSize(handler.getItem().size());
// Note: if you don't see the list content update, you might need to call
// listUsers.invalidate();
// here to force a refresh. I can't remember if calling setSize() is enough.
// TODO: set the previously selected, or focused, row
}
});
}
}
You'll need to add some error handling, in case the web service doesn't respond, or takes longer than a minute (you wouldn't want to be making a new request, if the last one hadn't finished).
But, this should get you started.
Note: once you fix the problem with running network code on the UI thread, you may still find that your code doesn't work. There could be problems fetching the web service data. You'll have to debug that. I am only showing you one problem with the code posted. If you still have problems with the web service fetch, post another question (with the UI thread problem fixed). Thanks.

BlackBerry Please Wait Screen with Time out

Hello I am trying to create a please wait screen.This screen will appear when my program requests data from web service and will hide when the process is finished.Also I want to add a time out if request process lasts longer than 90 seconds.
can anyone help or show me a guiding example about that matter.
public static void showBusyDialog() {
try
{
if (busyDialog == null) {
busyDialog = new Dialog("Please Wait", null, null, 0, Bitmap.getPredefinedBitmap(Bitmap.HOURGLASS));
busyDialog.setEscapeEnabled(false);
}
synchronized (Application.getEventLock()) {
busyDialog.show();
}
}
catch(Exception e)
{
}
}
and my hiding code is
public static void hideBusyDialog() {
try
{
if (busyDialog == null) {
// busyDialog = new Dialog("Please wait...", null, null, 0, Bitmap.getPredefinedBitmap(Bitmap.HOURGLASS));
busyDialog.setEscapeEnabled(false);
}
synchronized (Application.getEventLock()) {
busyDialog.close();
}
}catch(Exception e)
{
}
}
Many BlackBerry® smartphone applications need to wait for some network activity (or another blocking operation, which must process in the background), while still holding up the User Interface (UI) and displaying a progress indicator.
You can follow through this links
Links
Sample "Please Wait" screen - part 1
Sample "Please Wait" screen - part 2
Sample "Please Wait" screen - part 4
you can download simple examples for Please wait screen
PleaseWait1.zip 25 KB
PleaseWait2.zip 25 KB
PleaseWait3.zip 25 KB
Note :in case above Links not working then just follow following contents
There seem to be two common issues when programming this:
1) As applications are not allowed to block the Event Thread, how do they get the UI processing to wait?
2)How can the background Thread update the UI?
This article is intended to help with these issues and provide a fully functioning "Please Wait" sample Popup Screen. However, as there is quite a lot to explain, in this first article, we will just create a popup screen that will show itself, hold up the UI, and then remove itself once the background processing has finished. This does not give us any progress indication, nor does it let the user cancel the wait. These points will be covered in a followup article. But the code supplied with this article will be useful anyway, especially when the duration of the background processing is not known and the user may not cancel the processing.
First, we start with the background processing we need to run. While this could be anything, typically this will be network processing, like the following:
httpConn = (HttpConnection)Connector.open(_url + ";deviceside=true");
responseCode = httpConn.getResponseCode();
responseMessage = "Response Code: " + Integer.toString(responseCode);
To initiate this network processing, we have a MainScreen that contains
1) A BasicEditField that allows the entry of a URL
2) A RichTextField that should display the response code (or error message). Here are the important parts of that screen:
BasicEditField _requestedURLField = new BasicEditField("http://", "www.blackberry.com", 255, BasicEditField.FILTER_URL);
RichTextField _responseField = new RichTextField("<response code>", RichTextField.NON_FOCUSABLE);
We would like the MainScreen to be updated with the result. As noted above, background processing can't directly update the UI; UI updating code must be on the Event Thread. There are several ways to get a background process onto the Event Thread, see the related article for more. In this case, we will use the following code:
// Make things final so we can use them in the inner class
final String textString = responseMessage;
final RichTextField rtf = _resultField;
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
rtf.setText(textString);
}
});
Now we must define the PleaseWaitPopupScreen to be displayed while waiting.
To give the user something to look at while they are waiting, we have an animated .gif, which is diplayed using the code in the AnimatedGIFField (see related link). And, so the user knows what they are waiting for, the PleaseWaitPopupScreen is supplied with a String to display, as the following constructor shows:
private PleaseWaitPopupScreen(String text) {
super(new VerticalFieldManager(VerticalFieldManager.VERTICAL_SCROLL | VerticalFieldManager.VERTICAL_SCROLLBAR));
GIFEncodedImage ourAnimation = (GIFEncodedImage) GIFEncodedImage.getEncodedImageResource("cycle.agif");
_ourAnimation = new AnimatedGIFField(ourAnimation, Field.FIELD_HCENTER);
this.add(_ourAnimation);
_ourLabelField = new LabelField(text, Field.FIELD_HCENTER);
this.add(_ourLabelField);
}
PleaseWaitPopupScreen provides a method – showScreenAndWait(..) – which will create and display the Popup screen, run the Background processing, and then dismiss the Popup screen.
The final piece of the puzzle involves supplying showScreenAndWait(..) with the processing to run.
Java has the concept of a Runnable, which is an Object that contains a public void run() method that should be executed. In this case, we have the Connection code and screen update code, given above, that should be executed. So, this code is packaged up into a new Runnable Object, which is supplied to showScreenAndWait(..). And here is that method. Note how a new Thread is created and run.
public static void showScreenAndWait(final Runnable runThis, String text) {
final PleaseWaitPopupScreen thisScreen = new PleaseWaitPopupScreen(text);
Thread threadToRun = new Thread() {
public void run() {
// First, display this screen
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(thisScreen);
}
});
// Now run the code that must be executed in the Background
try {
runThis.run();
} catch (Throwable t) {
t.printStackTrace();
throw new RuntimeException("Exception detected while waiting: " + t.toString());
}
// Now dismiss this screen
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().popScreen(thisScreen);
}
});
}
};
threadToRun.start();
}
And this is the key part of the PleaseWaitPopupScreen. Note how this code will create and display a Popup screen to the user, including an animated icon, while it is running the background processing. Input from the user is blocked by the Popup screen until the processing completes. The originating screen is updated as a result of the background processing.
Download the associated .zip archive, which contains the source included in this article.
In the next article, we will extend this code to be able to handle:
a) Status updates from the Background Thread
b) "Time to go" indication
c) Being cancelled by the BlackBerry smartphone user
Just put timer after you show busy dialog.
showBusyDialog();
Timer timer = new Timer();
TimerTask task = new TimerTask() {
public void run() {
hideBusyDialog();
}
};
timer.schedule(task, 9000);
this is for time out. If the process finishes less than 90 seconds you should call
timer.cancel();
timer = null;
task = null;

Unable to close screen after the email attachment download is completed

I am using AttachmentDownloadManager class download method to download the email attachments to the device.I am displaying a progress screen while the attachments gets downloaded to device.In the downloadCompleted() event listener method, I am trying to stop/close the progress screen but unable to do so.
Below is the code snippet:
attachmentDownloadMngr = new AttachmentDownloadManager();
attachmentDownloadMngr.download(attachmentBodyPart, null, new IGAEmailAttachmentListener(this));
Below are DownloadProgressListener event listener methods:
public void updateProgress(Object element, int current, int total)
{
synchronized(UiApplication.getEventLock())
{
Ui.getUiEngine().pushGlobalScreen(progressScreen,1,UiEngine.GLOBAL_QUEUE);
}
}
public void downloadCompleted(Object element)
{
synchronized(UiApplication.getEventLock())
{
Ui.getUiEngine().popScreen(progressScreen);
}
}
public void downloadCancelled(Object element)
{
}
progressScreen is instance of PopupScreen where I am displaying a guagefield. The progress screen does not get any events even after the attachment download is completed.
Please help me to solve this issue.
You seem to be pushing a globalscreen every time you get a callback to updateprogress() . I wouldn't do it. I would rather push the globalscreen with the gaugefield when I start the download, and then set the value of gaugefield using gaugeField.setValue(value).
the way you are doing it would mean, the event thread pushes too many screens on to the stack, and I guess it would throw a run time exception and kill your app.

Resources