Skip to content
Snippets Groups Projects
Commit 1aa5ced8 authored by Jan Kožusznik's avatar Jan Kožusznik
Browse files

improve updateble values

parent 3a14790c
No related branches found
No related tags found
No related merge requests found
Showing
with 320 additions and 34 deletions
......@@ -2,12 +2,14 @@ package cz.it4i.fiji.haas.ui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Window;
import java.awt.im.InputMethodRequests;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Function;
import javax.swing.JDialog;
import javax.swing.JScrollPane;
......@@ -16,10 +18,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javafx.application.Platform;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.JFXPanel;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
public class FXFrame<C extends FXFrame.Controller> extends JDialog {
......@@ -36,6 +41,25 @@ public class FXFrame<C extends FXFrame.Controller> extends JDialog {
public interface Controller {
void init(Window frame);
static public <V> void executeAsync(Executor executor, Callable<V> action, Consumer<V> postAction) {
executor.execute(() -> {
V result;
try {
result = action.call();
postAction.accept(result);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
});
}
@SuppressWarnings("unchecked")
static public <U,T extends ObservableValue<U>> void setCellValueFactory(TableView<T> tableView,int index, Function<U, String> mapper) {
((TableColumn<T, String>) tableView.getColumns().get(index))
.setCellValueFactory(f -> new ObservableValueAdapter<U, String>(f.getValue(), mapper));
}
}
private static final long serialVersionUID = 1L;
......@@ -48,8 +72,8 @@ public class FXFrame<C extends FXFrame.Controller> extends JDialog {
this(null, fxmlFile);
}
public FXFrame(Frame applicationFrame, String string) {
super(applicationFrame);
public FXFrame(Window applicationFrame, String string) {
super(applicationFrame,ModalityType.MODELESS);
fxmlFile = string;
}
......
package cz.it4i.fiji.haas.ui;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function;
import javafx.beans.value.ObservableValue;
public class ObservableValueRegistry<T> {
private Function<T, Boolean> updateFunction;
private Function<T, Boolean> validateFunction;
private Consumer<T> removeConsumer;
public ObservableValueRegistry(Function<T, Boolean> validateFunction, Function<T, Boolean> updateFunction,
Consumer<T> removeConsumer) {
super();
this.validateFunction = validateFunction;
this.updateFunction = updateFunction;
this.removeConsumer = removeConsumer;
}
private Map<T,UpdatableObservableValue<T>> map = new HashMap<>();
public ObservableValue<T> addIfAbsent(T value) {
UpdatableObservableValue<T> uov = map.computeIfAbsent(value, v-> new UpdatableObservableValue<T>(v, updateFunction, validateFunction));
return uov;
}
public ObservableValue<T> remove(T value) {
return map.get(value);
}
public void update() {
for (UpdatableObservableValue<T> value : new LinkedList<>(map.values())) {
if(!value.update()) {
removeConsumer.accept(value.getValue());
}
}
}
}
package cz.it4i.fiji.haas.ui;
import java.util.function.Function;
import javafx.beans.value.ObservableValueBase;
public class UpdatableObservableValue<T> extends ObservableValueBase<T>{
private T wrapped;
private Function<T,Boolean> updateFunction;
private Function<T,Boolean> validateFunction;
public UpdatableObservableValue(T wrapped, Function<T, Boolean> updateFunction, Function<T, Boolean> validateFunction) {
super();
this.wrapped = wrapped;
this.updateFunction = updateFunction;
this.validateFunction = validateFunction;
}
@Override
public T getValue() {
return wrapped;
}
public boolean update() {
if(!validateFunction.apply(wrapped)) {
return false;
}
if(updateFunction.apply(wrapped)) {
fireValueChangedEvent();
}
return true;
}
}
package cz.it4i.fiji.haas_spim_benchmark.core;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public class Task {
private SPIMComputationAccessor outputHolder;
private String description;
private Collection<TaskComputation> computations;
private List<TaskComputation> computations;
private int numComputations;
public Task(SPIMComputationAccessor outputHolder, String description, int numComputations) {
......@@ -15,7 +15,7 @@ public class Task {
this.numComputations = numComputations;
}
public Collection<TaskComputation> getComputations() {
public List<TaskComputation> getComputations() {
if (computations == null) {
fillComputations();
}
......@@ -33,4 +33,9 @@ public class Task {
}
}
public void update() {
// TODO Auto-generated method stub
}
}
......@@ -29,6 +29,10 @@ public class TaskComputation {
updateState();//TASK 1011 it is not good idea update every time when state is requested
return state != null?state:JobState.Configuring;
}
public int getTimepoint() {
return timepoint;
}
private void updateState() {
String snakeOutput = outputHolder.getActualOutput();
......@@ -65,5 +69,10 @@ public class TaskComputation {
//
//or return
}
public void update() {
// TODO Auto-generated method stub
}
}
......@@ -15,7 +15,6 @@ import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
......@@ -28,7 +27,6 @@ import org.slf4j.LoggerFactory;
import cz.it4i.fiji.haas.ui.DummyProgress;
import cz.it4i.fiji.haas.ui.FXFrame;
import cz.it4i.fiji.haas.ui.ModalDialogs;
import cz.it4i.fiji.haas.ui.ObservableValueAdapter;
import cz.it4i.fiji.haas.ui.ProgressDialog;
import cz.it4i.fiji.haas.ui.TableViewContextMenu;
import cz.it4i.fiji.haas_java_client.JobState;
......@@ -37,7 +35,6 @@ import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.BenchmarkJob;
import cz.it4i.fiji.haas_spim_benchmark.core.Constants;
import cz.it4i.fiji.haas_spim_benchmark.core.FXFrameExecutorService;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import net.imagej.updater.util.Progress;
......@@ -98,11 +95,21 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
private void initMenu() {
TableViewContextMenu<BenchmarkJob> menu = new TableViewContextMenu<>(jobs);
menu.addItem("Create job", x -> executeWSCallAsync("Creating job", p -> manager.createJob()),
j -> true);
menu.addItem("Create job", x -> executeWSCallAsync("Creating job", p -> manager.createJob()), j -> true);
menu.addItem("Start job", job -> executeWSCallAsync("Starting job", p -> job.startJob(p)),
job -> notNullValue(job,
j -> j.getState() == JobState.Configuring || j.getState() == JobState.Finished));
menu.addItem("Show progress", job -> {
try {
new SPIMPipelineProgressViewWindow(root, job).setVisible(true);
} catch (IOException e) {
// TODO Auto-generated catch block
log.error(e.getMessage(), e);
}
}, job -> notNullValue(job, j -> j.getState() == JobState.Running || j.getState() == JobState.Finished
|| j.getState() == JobState.Failed));
menu.addItem("Download result", job -> executeWSCallAsync("Downloading data", p -> job.downloadData(p)),
job -> notNullValue(job,
j -> EnumSet.of(JobState.Failed, JobState.Finished).contains(j.getState()) && !j.downloaded()));
......@@ -129,31 +136,21 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
});
}
private <V> void executeAsync(Executor executor, Callable<V> action, Consumer<V> postAction) {
executor.execute(() -> {
V result;
try {
result = action.call();
postAction.accept(result);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
});
}
private void executeWSCallAsync(String title, P_JobAction action) {
executeWSCallAsync(title, true, action);
}
private void executeWSCallAsync(String title, boolean update, P_JobAction action) {
executeAsync(executorServiceWS, (Callable<Void>) ()->{
FXFrame.Controller.executeAsync(executorServiceWS, (Callable<Void>) () -> {
ProgressDialog dialog = ModalDialogs.doModal(new ProgressDialog(root, title),
WindowConstants.DO_NOTHING_ON_CLOSE);
action.doAction(dialog);
dialog.done();
return null;
}, x-> {if(update) updateJobs(); });
}, x -> {
if (update)
updateJobs();
});
}
private void updateJobs() {
......@@ -172,13 +169,11 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
throw new RuntimeException(e1);
}
executorServiceUI.execute(() -> {
Set<BenchmarkJob> old = new HashSet<BenchmarkJob>(jobs.getItems());
Map<BenchmarkJob, BenchmarkJob> actual;
try {
actual = manager.getJobs().stream().
collect(Collectors.toMap(job -> job, job -> job));
actual = manager.getJobs().stream().collect(Collectors.toMap(job -> job, job -> job));
} catch (IOException e) {
throw new RuntimeException(e);
}
......@@ -199,7 +194,7 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
});
});
});
}
private void initTable() {
......@@ -210,11 +205,8 @@ public class BenchmarkSPIMController implements FXFrame.Controller {
setCellValueFactory(4, j -> j.getEndTime().toString());
}
@SuppressWarnings("unchecked")
private void setCellValueFactory(int index, Function<BenchmarkJob, String> mapper) {
((TableColumn<BenchmarkJob, String>) jobs.getColumns().get(index))
.setCellValueFactory(f -> new ObservableValueAdapter<BenchmarkJob, String>(f.getValue(), mapper));
FXFrame.Controller.setCellValueFactory(jobs, index, mapper);
}
private interface P_JobAction {
......
package cz.it4i.fiji.haas_spim_benchmark.ui;
import java.util.function.Consumer;
import cz.it4i.fiji.haas.ui.ObservableValueRegistry;
import cz.it4i.fiji.haas_java_client.JobState;
import cz.it4i.fiji.haas_spim_benchmark.core.Task;
import cz.it4i.fiji.haas_spim_benchmark.core.TaskComputation;
public class ObservableTaskRegistry extends ObservableValueRegistry<Task>{
public ObservableTaskRegistry(
Consumer<Task> removeConsumer) {
super(x->true, t->update(t), removeConsumer);
}
private static boolean update(Task t) {
boolean result = true;
t.update();
for(TaskComputation tc: t.getComputations()) {
JobState oldState = tc.getState();
tc.update();
result &= oldState == tc.getState();
}
return result;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="912.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cz.it4i.fiji.haas_spim_benchmark.ui.SPIMPipelineProgressViewController">
<center>
<TableView fx:id="jobs" prefHeight="400.0" prefWidth="675.0" BorderPane.alignment="CENTER">
<columns>
<TableColumn prefWidth="101.0" text="Task name" />
</columns>
</TableView>
</center>
</BorderPane>
package cz.it4i.fiji.haas_spim_benchmark.ui;
import java.awt.Window;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.function.Function;
import java.util.stream.Collectors;
import cz.it4i.fiji.haas.ui.FXFrame;
import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.BenchmarkJob;
import cz.it4i.fiji.haas_spim_benchmark.core.Constants;
import cz.it4i.fiji.haas_spim_benchmark.core.Task;
import cz.it4i.fiji.haas_spim_benchmark.core.TaskComputation;
import javafx.beans.value.ObservableValue;
import javafx.fxml.FXML;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
public class SPIMPipelineProgressViewController implements FXFrame.Controller {
@FXML
private TableView<ObservableValue<Task>> tasks;
private BenchmarkJob job;
private Timer timer;
private ObservableTaskRegistry registry;
@Override
public void init(Window frame) {
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
super.windowClosed(e);
dispose();
}
});
timer = new Timer();
}
public void setBenchmarkJob(BenchmarkJob job) {
this.job = job;
registry = new ObservableTaskRegistry(task -> tasks.getItems().remove(registry.remove(task)));
fillTable();
}
private void fillTable() {
List<Task> tasks = job.getTasks();
if (tasks == null) {
timer.schedule(new TimerTask() {
@Override
public void run() {
fillTable();
}
}, Constants.HAAS_UPDATE_TIMEOUT / 10);
} else {
List<TaskComputation> computations = tasks.stream().map(task -> task.getComputations())
.collect(Collectors.<List<TaskComputation>>maxBy((a, b) -> a.size() - b.size())).get();
int i = 0;
FXFrame.Controller.setCellValueFactory(this.tasks, i++, (Function<Task, String>) v -> v.getDescription());
for (TaskComputation tc : computations) {
this.tasks.getColumns().add(new TableColumn<>(tc.getTimepoint() + ""));
int index = i;
FXFrame.Controller.setCellValueFactory(this.tasks, i, (Function<Task, String>) v -> {
List<TaskComputation> items = v.getComputations();
if (items.size() >= index) {
return "";
} else {
return v.getComputations().get(index).getState().toString();
}
});
}
this.tasks.getItems()
.addAll((tasks.stream().map(task -> registry.addIfAbsent(task)).collect(Collectors.toList())));
timer.schedule(new TimerTask() {
@Override
public void run() {
updateTable();
}
}, Constants.HAAS_UPDATE_TIMEOUT, Constants.HAAS_UPDATE_TIMEOUT);
}
}
private void updateTable() {
registry.update();
}
private void dispose() {
timer.cancel();
}
}
package cz.it4i.fiji.haas_spim_benchmark.ui;
import java.awt.Window;
import java.io.IOException;
import cz.it4i.fiji.haas.ui.FXFrame;
import cz.it4i.fiji.haas_spim_benchmark.core.BenchmarkJobManager.BenchmarkJob;
public class SPIMPipelineProgressViewWindow extends FXFrame<SPIMPipelineProgressViewController> {
private static final long serialVersionUID = 1L;
public SPIMPipelineProgressViewWindow(Window applicationFrame,BenchmarkJob job) throws IOException {
super(applicationFrame, "/cz/it4i/fiji/haas_spim_benchmark/ui/SPIMPipelineProgressView.fxml");
init(controller->controller.setBenchmarkJob(job));
}
}
package cz.it4i.fiji.haas;
import java.io.IOException;
import cz.it4i.fiji.haas_spim_benchmark.ui.SPIMPipelineProgressViewWindow;
public class RunSPIMPipelineView {
public static void main(String[] args) throws IOException {
new SPIMPipelineProgressViewWindow(null,null).setVisible(true);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment