How hook observable starting on delayed subscription in rxjava - reactive-programming

Usability: When user press button, search starts after 3000 msec. When search starts, progress bar should be shown.
I have delayed subscription:
Observable<SearchResult> delayedSearch = search
.delaySubscription(3000, TimeUnit.MILLISECONDS)
//not working
.doOnSubscribe(() -> log(should appear progress bar))
delayedSearch.subscribe(result -> log(should disappear progress bar));
Problem: I can't hook start observable's execution.
How best way to solve problem? Or maybe another solution?

I found solution.
I create showProgress observable:
Observable showProgress = Observable.create(subscriber -> {
log("showProgress")
subscriber.onNext(null);
subscriber.onCompleted();
}).subscribeOn(AndroidSchedulers.mainThread());
and add it before searching:
Observable<SearchResult> searchWithProgress = showProgress.flatMap((Func1) o -> search);
So I can use it like this:
Observable<SearchResult> delayedSearch = searchWithProgress.delaySubscription(3000, TimeUnit.MILLISECONDS);
delayedSearch.subscribe(result -> log(hideProgress);

Related

Scala swing wait for a button press after pressing a button

So What I want to do is to press a button and inside the ButtonClicked Event I want to wait completing the event, until I press a specific button/one of the specified buttons.
I also know that there are some similar questions to this topic but I wasnt able to find a fix out of the answers
So basically this:
reactions += {
case event.ButtonClicked(`rollDice`) =>
some code ...
wait for one of the specified buttons to be pressed and then continue
some code ...
Is there an easy way to solve this problem without the use of threads?
There are certainly some abstractions you could set up around the event layer, but you asked for "easy", so my suggestion is to set a flag/state when the dice are rolled, and then check for that flag in the other buttons' event handler.
private var postDiceRollState: Option[InfoRelatedToRollDice] = None
reactions += {
case event.ButtonClicked(`rollDice`) =>
// capture whatever info you need to pass along to the later button handler
val relevantInfo = /* some code... */
// store that info in the "state"
postDiceRollState = Some(relevantInfo)
case event.ButtonClicked(other) if isPostDiceRollButton(other) =>
// when the other button gets clicked, pull the relevant info from your "state"
postDiceRollState match {
case Some(relevantInfo) =>
postDiceRollState = None // clear state
doInterestingStuff(relevantInfo) // "some code..."
case None =>
// nothing happens if you didn't roll the dice first
}
}
Note: I represented the "flag" as an Option, under the assumption that you might have some information you want to capture about the rollDice event. If you don't actually have anything to put in there, you could represent your state as private var didRollDice: Boolean = false and set/clear would be setting it to true/false respectively.

How to show list of only the completed items?

I have a button and every time I press it should either show me the completed or uncompleted.
I tried to think of how everything should work. But can't figure out how to sort them properly, loop through all or loop through all completed.
tasks.forEach((task) {
if (task.completed) {
list.removeAt(task);
} else {
list.insert(tasks.indexOf(task), task);
}
});
The first press should show the completed only and next press only the uncompleted and it keeps going on like that.
Use where to filter out items from the list:
List completed = tasks.where( (task) => task.completed).toList();

Vala force refresh progressbar

I've made an aplication with vala where at some point I have to process a lot of files. I've created a window to choose a folder and then I get the paths of files and make some proces on them.
I've added a progress bar to this window to show how many files have been processed but for some reason it remains always empty.
Code about window:
this.files_window = new Gtk.Window();
this.files_window.window_position = Gtk.WindowPosition.CENTER;
this.files_window.destroy.connect (Gtk.main_quit);
// VBox:
Gtk.Box vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 5);
this.files_window.add (vbox);
// Buttons to open and close
Gtk.Button cancel = new Gtk.Button.with_label ("Cancel");
Gtk.Button select = new Gtk.Button.with_label ("Select");
vbox.add (select);
vbox.add (cancel);
// proogress bar
this.progress_bar = new Gtk.ProgressBar();
vbox.add(this.progress_bar);
// conect select to method do_stuff
select.clicked.connect (do_stuff);
this.files_window.show_all ();
As you can see, I connect the button "select" to the method "do_stuff" where I get the paths of selected files and make some process.
I update correctlly the fraction of the progres bar because I've added some prints to know if the value is correct and it is. It's just that the windows is not refreshing, possibly because all the work it is doing with the process of the files. Here is the code about do_stuff() method:
// some proces to get paths of files in the list sfiles
double fraction = 0.0;
this.progress_bar.set_fraction (fraction);
int processed_files = 0;
foreach (string sfile in sfiles) {
do_some_proces_to_file(sfile);
processed_files += 1;
fraction = (double)processed_files/(double)sfiles.length;
this.progress_bar.set_fraction (fraction);
stdout.printf("Real fraction: %f\n", this.progress_bar.get_fraction());
}
The printf shows that the value of the progres bar is being updated but in the window the bar is always empty.
Am I missing something? Is it the correct way to do the progres bar? Should I made another thread to do the stuff?
As #nemequ says, your code is blocking the main loop thread (which handles both user input and scheduling/drawing widget updates), hence it the progress bar is not updated until the method completes.
Using a thread is one way solve the problem, however using threads can lead to a lot of bugs however since it can be difficult to make even simple interactions between threads safe.
An async method avoids this by interleaving the code with the other work being done by the main loop. An async version of your do_stuff() would be pretty straight-forward to write, simply declare it async and put a yield in the for loop somewhere:
public async void do_stuff() {
...
foreach (string sfile in sfiles) {
// all of this is as before
do_some_proces_to_file(sfile);
processed_files += 1;
fraction = (double)processed_files/(double)sfiles.length;
this.progress_bar.set_fraction (fraction);
// Schedule the method to resume when idle, then
// yield control back to the caller
Idle.add(do_stuff.callback);
yield;
}
}
You can then kick it off from your click handler by calling: do_stuff.begin().
Unless there is some relevant code you're not showing, you're blocking the main loop. One option would be to do everything in a thread, and use an idle callback to update the UI. The basic idea is something like:
new GLib.Thread<void*>("file-processor", () => {
foreach (string sfile in sfiles) {
/* do stuff */
GLib.Idle.add(() => {
/* Update progress */
return false;
});
}
return null;
});
Depending on your application you may need to add a mutex to avoid race conditions. You may also need to add some logic for canceling the operation.
A better option might be to use a GLib.ThreadPool. You'd still want to update the UI from an idle callback, but this would allow each task to execute in parallel, which could provide a significant speed-up.
If I were you I'd probably wrap it all up in an async function to keep the API tidy, but you don't really have to.

JavaFX 8 Dialog

I'm implementing a document editor with JavaFX8 and e(fx)clipse and want to user to be informed when the export (write to disc) is ongoing. I'm using the main (GUI) Thread for this as I want to block the gui during this operation (which takes 2-3 seconds). During this operation I want to show a small popup to inform the user that the export is ongoing, nothing fancy.
#FXML
public void export() {
Dialog dialog = new Dialog();
dialog.setContentText("exporting ...");
dialog.show();
// some lenghty methods come here, ~equivalent to Thread.sleep(3000);
dialog.hide();
}
When I press the corresponding Button which invokes the export method, I get somehow two dialogs, one of them NOT closing and remaining open after the method has finished.
Does somebody has an idea what's happening here? I'm really interested in a simple solution, I don't need to have a progress bar etc..
Another possibility would be to show a wait-cursor before the operation starts and switching back to the default cursor after that. Unfortunately, this does also not seem to work. I understand that the UI is blocked during the "lengthty" operation, but I don't udnerstand why I cant change the UI before and after that operation....
Your example isn't very complete - however I would recommend using one of two approaches. However, you aren't putting the long process on a background thread which will FREEZE your app. You want to offload that process.
1) Use the ControlsFX Dialog which has a Progess Alert. Tie your work to either a Task or a Service and provide that to the alert. This will pop the alert up while the thread is active, and will automatically close it when done. If you have intermediary progress values, it can be used to update the progress bar.
Or if you don't want to use this dialog, you could do something like this:
Alert progressAlert = displayProgressDialog(message, stage);
Executors.newSingleThreadExecutor().execute(() -> {
try {
//Do you work here....
Platform.runLater(() ->forcefullyHideDialog(progressAlert));
} catch (Exception e) {
//Do what ever handling you need here....
Platform.runLater(() ->forcefullyHideDialog(progressAlert));
}
});
private Alert displayProgressDialog(String message, Stage stage) {
Alert progressAlert = new Alert(AlertType.NONE);
final ProgressBar progressBar = new ProgressBar();
progressBar.setMaxWidth(Double.MAX_VALUE);
progressBar.setPrefHeight(30);
final Label progressLabel = new Label(message);
progressAlert.setTitle("Please wait....");
progressAlert.setGraphic(progressBar);
progressAlert.setHeaderText("This will take a moment...");
VBox vbox = new VBox(20, progressLabel, progressBar);
vbox.setMaxWidth(Double.MAX_VALUE);
vbox.setPrefSize(300, 100);
progressAlert.getDialogPane().setContent(vbox);
progressAlert.initModality(Modality.WINDOW_MODAL);
progressAlert.initOwner(stage);
progressAlert.show();
return progressAlert;
}
private void forcefullyHideDialog(javafx.scene.control.Dialog<?> dialog) {
// for the dialog to be able to hide, we need a cancel button,
// so lets put one in now and then immediately call hide, and then
// remove the button again (if necessary).
DialogPane dialogPane = dialog.getDialogPane();
dialogPane.getButtonTypes().add(ButtonType.CANCEL);
dialog.hide();
dialogPane.getButtonTypes().remove(ButtonType.CANCEL);
}

Trigger an event after specific order of clicks

For a project I'm currently working on am trying to reach the following:
I have a simple page, on this page are 4, hidden and not visible elements,
they are simply formatted as this:
Basically all i want, is too build a sort of Easter egg, so when a user clicks these buttons in a specific order, i.e. link_4 -> link_1 -> link_3 -> link_2
it triggers a certain event, whatever this might be.
Ofcourse the event could only be triggered if the right combination/order of clicks have been done.
Any ideas how to go about this using jQuery?
var click_order = [];
$('a').click(function (e) {
click_order.push($(this).index());
if (click_order.slice(-4) == '3,0,2,1') {
// easter egg stuff
}
});