package rmblworx.tools.timey.gui;
import java.text.SimpleDateFormat;
import java.util.ResourceBundle;
import java.util.TimeZone;
import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import rmblworx.tools.timey.gui.config.Config;
import rmblworx.tools.timey.gui.config.ConfigManager;
import rmblworx.tools.timey.vo.TimeDescriptor;
/*
* Copyright 2014-2015 Christian Raue
* MIT License http://opensource.org/licenses/mit-license.php
*/
/**
* Controller für die Stoppuhr-GUI.
* @author Christian Raue {@literal <christian.raue@gmail.com>}
*/
public class StopwatchController extends Controller {
/**
* Formatiert Zeitstempel als Zeit-Werte.
*/
private SimpleDateFormat timeFormatter;
@FXML
private ResourceBundle resources;
@FXML
private Button stopwatchStartButton;
@FXML
private Button stopwatchStopButton;
@FXML
private ToggleButton stopwatchSplitTimeButton;
@FXML
private Button stopwatchResetButton;
@FXML
private Label stopwatchTimeLabel;
@FXML
private CheckBox stopwatchShowMillisecondsCheckbox;
/**
* Ob die Stoppuhr läuft.
*/
private boolean stopwatchRunning = false;
/**
* Stoppuhr-Zeit.
*/
private long stopwatchValue;
@FXML
private void initialize() {
stopwatchShowMillisecondsCheckbox.setSelected(ConfigManager.getCurrentConfig().isStopwatchShowMilliseconds());
setupTimeFormatter();
updateStopwatchTimeLabel();
}
/**
* Aktion bei Klick auf Start-Schaltfläche.
*/
@FXML
private void handleStartButtonClick() {
startStopwatch();
}
/**
* Aktion bei Klick auf Zwischenzeit-Schaltfläche.
*/
@FXML
private void handleSplitTimeButtonClick() {
getGuiHelper().runInThread(new Task<Void>() {
public Void call() {
getGuiHelper().getFacade().toggleTimeModeInStopwatch();
stopwatchStopButton.setDisable(stopwatchSplitTimeButton.isSelected());
return null;
}
}, resources);
}
/**
* Aktion bei Klick auf Stop-Schaltfläche.
*/
@FXML
private void handleStopButtonClick() {
stopStopwatch();
}
/**
* Aktion bei Klick auf Zurücksetzen-Schaltfläche.
*/
@FXML
private void handleResetButtonClick() {
getGuiHelper().runInThread(new Task<Void>() {
public Void call() {
getGuiHelper().getFacade().resetStopwatch();
stopwatchValue = 0L;
Platform.runLater(new Runnable() {
public void run() {
updateStopwatchTimeLabel();
stopwatchSplitTimeButton.setSelected(false);
stopwatchStopButton.setDisable(false);
stopwatchStartButton.requestFocus();
}
});
return null;
}
}, resources);
}
/**
* Aktion bei Klick auf Millisekunden-Checkbox.
*/
@FXML
private void handleShowMillisecondsCheckboxClick() {
ConfigManager.getCurrentConfig().setStopwatchShowMilliseconds(stopwatchShowMillisecondsCheckbox.isSelected());
setupTimeFormatter();
updateStopwatchTimeLabel();
}
/**
* Startet die Stoppuhr.
*/
private void startStopwatch() {
if (stopwatchRunning) {
return;
}
stopwatchRunning = true;
final Task<Void> task = new Task<Void>() {
private static final long SLEEP_TIME_FINE_GRAINED = 5L;
private static final long SLEEP_TIME_COARSE_GRAINED = 1000L;
public Void call() throws InterruptedException {
final Config config = ConfigManager.getCurrentConfig();
final TimeDescriptor td = getGuiHelper().getFacade().startStopwatch();
Platform.runLater(new Runnable() {
public void run() {
stopwatchStartButton.setVisible(false);
stopwatchSplitTimeButton.setDisable(false);
stopwatchStopButton.setVisible(true);
stopwatchStopButton.requestFocus();
}
});
while (stopwatchRunning) {
stopwatchValue = td.getMilliSeconds();
updateMessage(timeFormatter.format(stopwatchValue));
Thread.sleep(config.isStopwatchShowMilliseconds() ? SLEEP_TIME_FINE_GRAINED : SLEEP_TIME_COARSE_GRAINED);
}
return null;
}
};
task.messageProperty().addListener(new ChangeListener<String>() {
public void changed(final ObservableValue<? extends String> property, final String oldValue, final String newValue) {
stopwatchTimeLabel.setText(newValue);
}
});
getGuiHelper().runInThread(task, resources);
}
/**
* Stoppt die Stoppuhr.
*/
private void stopStopwatch() {
if (!stopwatchRunning) {
return;
}
stopwatchRunning = false;
getGuiHelper().runInThread(new Task<Void>() {
public Void call() throws InterruptedException {
getGuiHelper().getFacade().stopStopwatch();
Platform.runLater(new Runnable() {
public void run() {
stopwatchStartButton.setVisible(true);
stopwatchStartButton.requestFocus();
stopwatchSplitTimeButton.setDisable(true);
stopwatchSplitTimeButton.setSelected(false);
stopwatchStopButton.setVisible(false);
}
});
return null;
}
}, resources);
}
/**
* Initialisiert den Zeitformatierer bzw. aktualisiert dessen Format.
*/
private void setupTimeFormatter() {
if (timeFormatter == null) {
timeFormatter = new SimpleDateFormat();
timeFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
}
timeFormatter.applyPattern(ConfigManager.getCurrentConfig().isStopwatchShowMilliseconds() ? "HH:mm:ss.SSS" : "HH:mm:ss");
}
/**
* Aktualisiert die Anzeige der gemessenen Zeit, falls die Stoppuhr nicht läuft.
*/
private void updateStopwatchTimeLabel() {
if (!stopwatchRunning) {
stopwatchTimeLabel.setText(timeFormatter.format(stopwatchValue));
}
}
}