/*
Copywrite 2016-2017 Will Winder
This file is part of Universal Gcode Sender (UGS).
UGS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
UGS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with UGS. If not, see <http://www.gnu.org/licenses/>.
*/
package com.willwinder.universalgcodesender.uielements.panels;
import com.willwinder.universalgcodesender.i18n.Localization;
import com.willwinder.universalgcodesender.model.BackendAPI;
import javax.swing.JLabel;
import javax.swing.JPanel;
import com.willwinder.universalgcodesender.Utils;
import com.willwinder.universalgcodesender.listeners.ControllerListener;
import com.willwinder.universalgcodesender.listeners.ControllerStatus;
import com.willwinder.universalgcodesender.listeners.UGSEventListener;
import com.willwinder.universalgcodesender.model.Position;
import com.willwinder.universalgcodesender.model.UGSEvent;
import static com.willwinder.universalgcodesender.model.UGSEvent.ControlState.COMM_SENDING;
import static com.willwinder.universalgcodesender.model.UGSEvent.FileState.FILE_LOADED;
import com.willwinder.universalgcodesender.types.GcodeCommand;
import com.willwinder.universalgcodesender.utils.GUIHelpers;
import com.willwinder.universalgcodesender.utils.GcodeStreamReader;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.Timer;
import net.miginfocom.swing.MigLayout;
/**
*
* @author wwinder
*/
public class SendStatusPanel extends JPanel implements UGSEventListener, ControllerListener {
private static final String AL_RIGHT = "al right";
private final BackendAPI backend;
private final JLabel rowsLabel = new JLabel(Localization.getString("mainWindow.swing.rowsLabel"));
private final JLabel sentRowsLabel = new JLabel(Localization.getString("mainWindow.swing.sentRowsLabel"));
private final JLabel remainingRowsLabel = new JLabel(Localization.getString("mainWindow.swing.remainingRowsLabel"));
private final JLabel remainingTimeLabel = new JLabel(Localization.getString("mainWindow.swing.remainingTimeLabel"));
private final JLabel durationLabel = new JLabel(Localization.getString("mainWindow.swing.durationLabel"));
private final JLabel rowsValue = new JLabel();
private final JLabel sentRowsValue = new JLabel();
private final JLabel remainingRowsValue = new JLabel();
private final JLabel remainingTimeValue = new JLabel();
private final JLabel durationValue = new JLabel();
Timer timer;
public SendStatusPanel() {
this(null);
}
public SendStatusPanel(BackendAPI b) {
backend = b;
if (backend != null) {
backend.addUGSEventListener(this);
backend.addControllerListener(this);
}
initComponents();
resetSentRowLabels();
if (backend.isSendingFile()) {
beginSend();
}
}
private void update() {
durationValue.setText(Utils.formattedMillis(backend.getSendDuration()));
setRemainingTime(backend.getSendRemainingDuration());
sentRowsValue.setText(""+backend.getNumSentRows());
remainingRowsValue.setText("" + backend.getNumRemainingRows());
}
private void beginSend() {
// Timer for updating duration labels.
ActionListener actionListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
update();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
};
this.resetTimerLabels();
if (timer != null){ timer.stop(); }
timer = new Timer(1000, actionListener);
// Note: there is a divide by zero error in the timer because it uses
// the rowsValueLabel that was just reset.
try {
timer.start();
} catch (Exception e) {
timer.stop();
GUIHelpers.displayErrorDialog(e.getMessage());
}
}
private void endSend() {
setRemainingTime(Utils.formattedMillis(0));
remainingRowsValue.setText("" + backend.getNumRemainingRows());
java.awt.EventQueue.invokeLater(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {}
// Stop the timer after a delay to make sure it is updated.
if (timer != null && timer.isRunning()) {
timer.stop();
}
});
}
private void resetTimerLabels() {
// Reset labels
this.durationValue.setText("00:00:00");
if (this.backend != null && this.backend.isConnected()) {
setRemainingTime(backend.getSendDuration());
} else {
setRemainingTime("--:--:--");
}
}
private void setRemainingTime(long millis) {
if (millis < 0) {
setRemainingTime("estimating...");
} else if (millis == 0) {
setRemainingTime("--:--:--");
} else {
setRemainingTime(Utils.formattedMillis(millis));
}
}
private void setRemainingTime(String text) {
this.remainingTimeValue.setText(text);
}
public String getDuration() {
return this.durationValue.getText();
}
private void resetSentRowLabels() {
long numRows = 0;
if (backend.getProcessedGcodeFile() != null) {
try {
try (GcodeStreamReader gsr = new GcodeStreamReader(backend.getProcessedGcodeFile())) {
numRows = gsr.getNumRows();
System.out.println("NUM ROWS: " + numRows);
}
} catch (IOException ex) {}
}
// Reset labels
String totalRows = String.valueOf(numRows);
resetTimerLabels();
this.sentRowsValue.setText("0");
this.remainingRowsValue.setText(totalRows);
this.rowsValue.setText(totalRows);
}
private void initComponents() {
// MigLayout... 3rd party layout library.
setLayout(new MigLayout("fill, wrap 2"));
add(rowsLabel, AL_RIGHT);
add(rowsValue);
add(sentRowsLabel, AL_RIGHT);
add(sentRowsValue);
add(remainingRowsLabel, AL_RIGHT);
add(remainingRowsValue);
add(remainingTimeLabel, AL_RIGHT);
add(remainingTimeValue);
add(durationLabel, AL_RIGHT);
add(durationValue);
}
@Override
public void UGSEvent(com.willwinder.universalgcodesender.model.UGSEvent evt) {
// Look for a send beginning.
if (evt.isStateChangeEvent() && evt.getControlState() == COMM_SENDING) {
if (backend.isSendingFile()) {
beginSend();
}
}
// On file loaded event, reset the rows.
if (evt.isFileChangeEvent() && evt.getFileState() == FILE_LOADED) {
resetSentRowLabels();
}
}
// Controller events below.
@Override
public void controlStateChange(UGSEvent.ControlState state) {
}
@Override
public void fileStreamComplete(String filename, boolean success) {
endSend();
}
@Override
public void commandSkipped(GcodeCommand command) {
}
@Override
public void commandSent(GcodeCommand command) {
}
@Override
public void commandComplete(GcodeCommand command) {
}
@Override
public void commandComment(String comment) {
}
@Override
public void probeCoordinates(Position p) {
}
@Override
public void messageForConsole(MessageType type, String msg) {
}
@Override
public void statusStringListener(ControllerStatus status) {
}
@Override
public void postProcessData(int numRows) {
}
}