Skip to content

Commit 004c56c

Browse files
authored
Merge pull request #34 from flimlib/fiji-future-fixes
Fix bugs and simplify FLIMJ development
2 parents eca224a + ca0f1ea commit 004c56c

File tree

12 files changed

+213
-178
lines changed

12 files changed

+213
-178
lines changed

src/main/java/flimlib/flimj/ui/controller/ConfigCtrl.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,23 @@
2323

2424
import com.google.gson.JsonParser;
2525
import com.google.gson.JsonElement;
26+
2627
import java.io.File;
2728
import java.nio.file.Files;
2829
import java.io.FileWriter;
2930
import java.io.IOException;
30-
import org.scijava.widget.FileWidget;
31+
3132
import javafx.fxml.FXML;
3233
import javafx.scene.control.Button;
3334
import javafx.scene.control.Alert;
3435
import javafx.scene.control.Alert.AlertType;
36+
import javafx.stage.FileChooser;
37+
import javafx.stage.Stage;
38+
3539
import flimlib.flimj.FitParams;
3640
import flimlib.flimj.ui.controls.NumericSpinner;
3741
import flimlib.flimj.ui.FitProcessor.FitType;
42+
3843
import net.imglib2.type.numeric.real.FloatType;
3944

4045
/**
@@ -44,7 +49,7 @@ public class ConfigCtrl extends AbstractCtrl {
4449
@FXML
4550
private NumericSpinner binSizeSpinner;
4651

47-
@FXML
52+
@FXML
4853
private Button configLoadButton;
4954

5055
@FXML
@@ -53,10 +58,15 @@ public class ConfigCtrl extends AbstractCtrl {
5358
@Override
5459
public void initialize() {
5560

61+
// initialize a file chooser
62+
final var fcStage = new Stage();
63+
final var fcUI = new FileChooser();
64+
5665
configSaveButton.setOnAction(event -> {
57-
File cfgSavePath = getUIs().chooseFile("Choose config save path", new File("fit_config.txt"),
58-
FileWidget.SAVE_STYLE);
59-
if (cfgSavePath != null) {
66+
fcUI.setTitle("Choose config save path");
67+
fcUI.setInitialFileName("fit_config.txt");
68+
File cfgSavePath = fcUI.showSaveDialog(fcStage);
69+
if (cfgSavePath != null) {
6070
try {
6171
FileWriter writer = new FileWriter(cfgSavePath);
6272
String paramsJSONString = fp.getParams().toJSON();
@@ -75,9 +85,9 @@ public void initialize() {
7585
});
7686

7787
configLoadButton.setOnAction(event -> {
78-
File cfgLoadPath = getUIs().chooseFile("Choose config file", null,
79-
FileWidget.OPEN_STYLE);
80-
if (cfgLoadPath != null) {
88+
fcUI.setTitle("Choose config file");
89+
File cfgLoadPath = fcUI.showOpenDialog(fcStage);
90+
if (cfgLoadPath != null) {
8191
String cfgPath = cfgLoadPath.getPath();
8292
if (cfgPath.endsWith(".txt")) {
8393
try {

src/main/java/flimlib/flimj/ui/controller/PlotCtrl.java

Lines changed: 130 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
* it under the terms of the GNU General Public License as
99
* published by the Free Software Foundation, either version 3 of the
1010
* License, or (at your option) any later version.
11-
*
11+
*
1212
* This program is distributed in the hope that it will be useful,
1313
* but WITHOUT ANY WARRANTY; without even the implied warranty of
1414
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1515
* GNU General Public License for more details.
16-
*
16+
*
1717
* You should have received a copy of the GNU General Public
1818
* License along with this program. If not, see
1919
* <http://www.gnu.org/licenses/gpl-3.0.html>.
@@ -23,6 +23,7 @@
2323

2424
import java.util.ArrayList;
2525
import java.util.List;
26+
2627
import javafx.application.Platform;
2728
import javafx.beans.property.ObjectProperty;
2829
import javafx.beans.property.SimpleObjectProperty;
@@ -38,17 +39,24 @@
3839
import javafx.scene.chart.XYChart.Data;
3940
import javafx.scene.chart.XYChart.Series;
4041
import javafx.scene.control.TextField;
42+
import javafx.scene.control.ToggleButton;
4143
import javafx.scene.image.ImageView;
4244
import javafx.scene.image.WritableImage;
45+
import javafx.scene.input.MouseEvent;
4346
import javafx.scene.layout.AnchorPane;
47+
import javafx.scene.shape.Circle;
48+
import javafx.scene.shape.Line;
49+
4450
import org.controlsfx.control.HiddenSidesPane;
4551
import org.controlsfx.control.SegmentedButton;
52+
53+
import net.imglib2.type.numeric.real.FloatType;
54+
4655
import flimlib.flimj.FitParams;
4756
import flimlib.flimj.FitResults;
4857
import flimlib.flimj.ui.Utils;
4958
import flimlib.flimj.ui.VariableScaleAxis;
5059
import flimlib.flimj.ui.controls.NumericSpinner;
51-
import net.imglib2.type.numeric.real.FloatType;
5260

5361
/**
5462
* The controller of the "Plot" tab.
@@ -59,15 +67,21 @@ public class PlotCtrl extends AbstractCtrl {
5967
private static final int FIT_IDX = 1;
6068
private static final int RES_IDX = 2;
6169
private static final int IRF_IDX = 3;
62-
6370
private static final int BEG_IDX = 0;
6471
private static final int END_IDX = 1;
65-
6672
private static final int N_PLOTS = 4;
6773

6874
/** cursors */
6975
@FXML
70-
private Group lCsr, rCsr;
76+
private Group lCsr, rCsr, lCsr_res, rCsr_res;
77+
78+
/** cursor circle elements*/
79+
@FXML
80+
private Circle lCsrCircle, rCsrCircle;
81+
82+
/** cursor line elements*/
83+
@FXML
84+
private Line lCsrBar, rCsrBar, lCsrBar_res, rCsrBar_res;
7185

7286
/** cursor position spinners */
7387
@FXML
@@ -96,6 +110,9 @@ public class PlotCtrl extends AbstractCtrl {
96110
@FXML
97111
private ImageView frostImageView;
98112

113+
@FXML
114+
private ToggleButton linTB, logTB;
115+
99116
/** cursor positions */
100117
private ObjectProperty<Double> lCsrPos, rCsrPos;
101118

@@ -128,22 +145,41 @@ public class PlotCtrl extends AbstractCtrl {
128145
@SuppressWarnings("unchecked")
129146
public void initialize() {
130147
// initialize properties with invalid values (corrected by refresh())
131-
lCsrPos = new SimpleObjectProperty<>();
132-
lCsrPos.set(-1.0);
133-
rCsrPos = new SimpleObjectProperty<>();
134-
rCsrPos.set(-1.0);
135-
fitStart = new SimpleObjectProperty<>();
136-
fitStart.set(-1);
137-
fitEnd = new SimpleObjectProperty<>();
138-
fitEnd.set(-1);
148+
lCsrPos = new SimpleObjectProperty<>(-1.0);
149+
rCsrPos = new SimpleObjectProperty<>(-1.0);
150+
fitStart = new SimpleObjectProperty<>(-1);
151+
fitEnd = new SimpleObjectProperty<>(-1);
139152
lCsrSpinner.setMin(0.0);
140153
rCsrSpinner.setMin(0.0);
141154
lCsrSpinner.setMax(0.0);
142155
rCsrSpinner.setMax(0.0);
143156

157+
// set cursor initial positions
158+
lCsr.setTranslateX(0);
159+
rCsr.setTranslateX(fitPlotAreaPane.getWidth());
160+
161+
// bind the X pos of the residual cursors so they move together
162+
lCsr_res.translateXProperty().bind(lCsr.translateXProperty());
163+
rCsr_res.translateXProperty().bind(rCsr.translateXProperty());
164+
165+
// fit the height of the bar with the plot height size
166+
lCsrBar.endYProperty().bind(fitPlotAreaPane.heightProperty().subtract(1));
167+
rCsrBar.endYProperty().bind(fitPlotAreaPane.heightProperty().subtract(1));
168+
lCsrBar_res.endYProperty().bind(fitPlotAreaPane.heightProperty().subtract(1));
169+
lCsrBar_res.endYProperty().bind(fitPlotAreaPane.heightProperty().subtract(1));
170+
171+
// link the two toggle buttons to the segmented button
172+
fitYScaleSB.getButtons().addAll(linTB, logTB);
173+
linTB.setSelected(true);
174+
175+
// initialize cursor listeners
144176
initListeners(rCsr, rCsrPos, rCsrSpinner, fitEnd);
145177
initListeners(lCsr, lCsrPos, lCsrSpinner, fitStart);
146178

179+
// initialize cursor mouse event handlers
180+
initCursorEventHandlers(lCsr);
181+
initCursorEventHandlers(rCsr);
182+
147183
fitPlotAreaPane.widthProperty().addListener((obs, oldVal, newVal) -> {
148184
// == 0 at init
149185
if (oldVal.floatValue() != 0) {
@@ -220,6 +256,17 @@ else if (oldVal != null)
220256
});
221257
}
222258

259+
/**
260+
* Clamps a value between min and max.
261+
* @param value The value to clamp.
262+
* @param min The minimum allowed value.
263+
* @param max The maximum allowed value.
264+
* @return The clamped value.
265+
*/
266+
private double clamp(double value, double min, double max) {
267+
return Math.max(min, Math.min(value, max));
268+
}
269+
223270
@Override
224271
protected void refresh(FitParams<FloatType> params, FitResults results) {
225272
nIntervals = params.trans.length - 1;
@@ -248,6 +295,75 @@ protected void refresh(FitParams<FloatType> params, FitResults results) {
248295

249296
}
250297

298+
/**
299+
* Sets up mouse event handlers for a cursor group.
300+
*
301+
* @param cursor The cursor group to initialize.
302+
*/
303+
private void initCursorEventHandlers(Group cursor) {
304+
// find the circle within the cursor group
305+
var csrCircle = (Circle) cursor.lookup("#" + cursor.getId() + "Circle");
306+
307+
// create onMouseEntered event handler
308+
cursor.setOnMouseEntered(event -> {
309+
double newCenterY = clamp(event.getY(),
310+
csrCircle.getRadius() * 2.5,
311+
fitPlotAreaPane.getHeight() - csrCircle.getRadius() * 2.5);
312+
csrCircle.setCenterY(newCenterY);
313+
csrCircle.setScaleX(2);
314+
csrCircle.setScaleY(2);
315+
});
316+
317+
// create onMouseExited event handler
318+
cursor.setOnMouseExited(event -> {
319+
csrCircle.setScaleX(1);
320+
csrCircle.setScaleY(1);
321+
});
322+
323+
// create onMouseDragged event handler
324+
cursor.setOnMouseDragged(event -> {
325+
double newTranslateX = cursor.getTranslateX() + event.getX();
326+
double min = 0.0;
327+
double max = fitPlotAreaPane.getWidth();
328+
if (cursor == rCsr) {
329+
min = lCsr.getTranslateX();
330+
} else if (cursor == lCsr) {
331+
max = rCsr.getTranslateX();
332+
}
333+
cursor.setTranslateX(clamp(newTranslateX, min, max));
334+
});
335+
}
336+
337+
/**
338+
* Handle "mouse entered" events.
339+
*
340+
* @param event A mouse movement event.
341+
*/
342+
@FXML
343+
private void handleMouseEntered(MouseEvent event) {
344+
((Group) event.getSource()).getOnMouseEntered().handle(event);
345+
}
346+
347+
/**
348+
* Handle "mouse exited" events.
349+
*
350+
* @param event A mouse movement event.
351+
*/
352+
@FXML
353+
private void handleMouseExited(MouseEvent event) {
354+
((Group) event.getSource()).getOnMouseExited().handle(event);
355+
}
356+
357+
/**
358+
* Handle "mouse dragged" events.
359+
*
360+
* @param event A mouse movement event.
361+
*/
362+
@FXML
363+
private void handleMouseDragged(MouseEvent event) {
364+
((Group) event.getSource()).getOnMouseDragged().handle(event);
365+
}
366+
251367
/**
252368
* Adds change listeners to critical values so that they work together.
253369
*

src/main/java/flimlib/flimj/ui/controller/SettingsCtrl.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939

4040
import org.scijava.ui.DialogPrompt.MessageType;
4141
import org.scijava.ui.DialogPrompt.OptionType;
42-
import org.scijava.widget.FileWidget;
4342

4443
import flimlib.NoiseType;
4544
import flimlib.flimj.FitParams;
@@ -50,6 +49,7 @@
5049
import flimlib.flimj.ui.Utils;
5150
import flimlib.flimj.ui.controls.NumericSpinner;
5251
import flimlib.flimj.ui.controls.NumericTextField;
52+
5353
import javafx.animation.Timeline;
5454
import javafx.animation.KeyFrame;
5555
import javafx.application.Platform;
@@ -68,6 +68,8 @@
6868
import javafx.scene.layout.GridPane;
6969
import javafx.scene.text.Font;
7070
import javafx.scene.text.Text;
71+
import javafx.stage.FileChooser;
72+
import javafx.stage.Stage;
7173
import javafx.util.StringConverter;
7274
import javafx.util.Duration;
7375

@@ -122,11 +124,17 @@ public class SettingsCtrl extends AbstractCtrl {
122124

123125
@Override
124126
public void initialize() {
127+
// initialize buffers
125128
paramLabels = new ArrayList<>();
126129
paramValues = new ArrayList<>();
127130
paramFixed = new ArrayList<>();
128131
paramIndices = new ArrayList<>();
129132
presentDatasets = new HashMap<>();
133+
134+
// initialize file chooser
135+
final var fcStage = new Stage();
136+
final var fcUI = new FileChooser();
137+
130138
// keep only the table header (remove the preview parameters)
131139
paramPane.getChildren().removeIf(child -> GridPane.getRowIndex(child) > 0);
132140

@@ -297,8 +305,8 @@ public NoiseType fromString(String string) {
297305
// the name of selected dataset
298306
String currentSelection = oldVal;
299307
// choose from file
300-
File irfFile = getUIs().chooseFile("Choose IRF transient file", null,
301-
FileWidget.OPEN_STYLE);
308+
fcUI.setTitle("Choose IRF transiet file");
309+
File irfFile = fcUI.showOpenDialog(fcStage);
302310
if (irfFile != null) {
303311
// not cancelled
304312
String irfPath = irfFile.getPath();

0 commit comments

Comments
 (0)