/* This file is part of Wattzap Community Edition.
*
* Wattzap Community Edtion 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.
*
* Wattzap Community Edition 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 Wattzap. If not, see <http://www.gnu.org/licenses/>.
*/
package com.wattzap.view;
import java.awt.Color;
import java.awt.Font;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import com.wattzap.controller.MessageBus;
import com.wattzap.controller.MessageCallback;
import com.wattzap.controller.Messages;
import com.wattzap.model.RouteReader;
import com.wattzap.model.UserPreferences;
import com.wattzap.model.dto.Telemetry;
import com.wattzap.model.dto.TrainingItem;
/**
* Used when ANT+ Stick is connected and configured
*
* @author David George (c) Copyright 2014
* @date 5 February 2014
*/
public class AntOdometer extends JPanel implements MessageCallback {
private static final long serialVersionUID = -7939830514817673972L;
private JLabel speedText;
private JLabel distText;
private JLabel slopeText;
private JLabel levelText;
private JLabel speedLabel;
private JLabel distanceLabel;
private JLabel elevationLabel;
private JLabel slopeLabel;
private JLabel cadenceLabel;
private JLabel hrLabel;
private JLabel powerLabel;
private JLabel chronoLabel;
private int type = RouteReader.SLOPE;
private TrainingItem current;
private static Logger logger = LogManager.getLogger("Odometer");
private final Color skyBlue = new Color(0, 154, 237);
private final Color textColor = new Color(240, 244, 112);
private DateFormat timeFormat;
private long startTime = 0;
private double totalDistance = 0;
private final UserPreferences userPrefs = UserPreferences.INSTANCE;
public AntOdometer() {
super();
timeFormat = new SimpleDateFormat("HH:mm:ss");
timeFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
setBackground(Color.BLACK);
int style1 = Font.CENTER_BASELINE;
Font font1 = new Font("Arial", style1, 13);
int style = Font.BOLD | Font.ITALIC;
Font font = new Font("Arial", style, 30);
MigLayout layout = new MigLayout("fillx", "[center]", "[][shrink 0]");
this.setLayout(layout);
speedText = new JLabel();
speedText.setFont(font1);
speedText.setForeground(textColor);
add(speedText);
distText = new JLabel();
distText.setFont(font1);
distText.setForeground(textColor);
add(distText);
JLabel pwrText = new JLabel();
pwrText.setFont(font1);
pwrText.setText(userPrefs.getString("power"));
pwrText.setForeground(textColor);
add(pwrText);
JLabel hrText = new JLabel();
hrText.setFont(font1);
hrText.setText(userPrefs.getString("heartrate"));
hrText.setForeground(textColor);
add(hrText);
JLabel cadText = new JLabel();
cadText.setFont(font1);
cadText.setText(userPrefs.getString("cadence"));
cadText.setForeground(textColor);
add(cadText);
slopeText = new JLabel();
slopeText.setFont(font1);
slopeText.setText(userPrefs.getString("slope") + " %");
slopeText.setForeground(textColor);
add(slopeText);
levelText = new JLabel();
levelText.setFont(font1);
levelText.setText(userPrefs.getString("altitude"));
levelText.setForeground(textColor);
add(levelText);
JLabel resistanceText = new JLabel();
resistanceText.setFont(font1);
resistanceText.setText(userPrefs.getString("stopwatch"));
resistanceText.setForeground(textColor);
add(resistanceText, "Wrap");
speedLabel = new JLabel();
speedLabel.setFont(font);
speedLabel.setText("0.0");
speedLabel.setForeground(Color.WHITE);
add(speedLabel);
distanceLabel = new JLabel();
distanceLabel.setFont(font);
distanceLabel.setText("0.0");
distanceLabel.setForeground(Color.WHITE);
add(distanceLabel);
powerLabel = new JLabel();
powerLabel.setFont(font);
powerLabel.setText("0");
powerLabel.setForeground(Color.WHITE);
add(powerLabel);
hrLabel = new JLabel();
hrLabel.setFont(font);
hrLabel.setText("0");
hrLabel.setForeground(Color.WHITE);
add(hrLabel);
cadenceLabel = new JLabel();
cadenceLabel.setFont(font);
cadenceLabel.setText("0");
cadenceLabel.setForeground(Color.WHITE);
add(cadenceLabel);
slopeLabel = new JLabel();
slopeLabel.setFont(font);
slopeLabel.setText("0.0");
slopeLabel.setForeground(Color.WHITE);
add(slopeLabel);
elevationLabel = new JLabel();
elevationLabel.setFont(font);
elevationLabel.setForeground(Color.WHITE);
elevationLabel.setText("0");
add(elevationLabel);
chronoLabel = new JLabel();
chronoLabel.setFont(font);
chronoLabel.setForeground(Color.WHITE);
add(chronoLabel);
chronoLabel.setText("00:00:00");
initLabels(userPrefs.isMetric());
MessageBus.INSTANCE.register(Messages.TRAININGITEM, this);
MessageBus.INSTANCE.register(Messages.SPEED, this);
MessageBus.INSTANCE.register(Messages.CADENCE, this);
MessageBus.INSTANCE.register(Messages.HEARTRATE, this);
MessageBus.INSTANCE.register(Messages.GPXLOAD, this);
MessageBus.INSTANCE.register(Messages.START, this);
}
private void initLabels(boolean metric) {
if (metric) {
speedText.setText(userPrefs.getString("speed") + " (km/h)");
distText.setText(userPrefs.getString("distance") + " (km)");
} else {
speedText.setText(userPrefs.getString("speed") + " (mph)");
distText.setText(userPrefs.getString("distance") + " (miles)");
}
}
@Override
public void callback(Messages message, Object o) {
switch (message) {
case SPEED:
Telemetry t = (Telemetry) o;
if (startTime == 0) {
startTime = t.getTime();
}
boolean metric = userPrefs.isMetric();
if (userPrefs.isMetric()) {
speedLabel.setText(String.format("%.1f", t.getSpeedKMH()));
distanceLabel.setText(String.format("%.3f", t.getDistanceKM()));
} else {
speedLabel.setText(String.format("%.1f", t.getSpeedMPH()));
distanceLabel.setText(String.format("%.3f",
t.getDistanceMiles()));
}
int power = t.getPower();
if (power != -1) {
if (current != null) {
int i = current.isPowerInRange(power);
if (i < 0) {
powerLabel.setForeground(skyBlue);
powerLabel.setText("" + power);
} else if (i > 0) {
powerLabel.setForeground(Color.RED);
powerLabel.setText("" + power);
} else {
powerLabel.setForeground(Color.WHITE);
powerLabel.setText("" + power);
}
} else {
powerLabel.setText("" + power);
}
}
chronoLabel.setText(timeFormat.format(new Date(t.getTime()
- startTime)));
switch (type) {
case RouteReader.POWER:
if (userPrefs.isMetric()) {
// remaining distance
elevationLabel.setText(String.format("%.3f",
(totalDistance - t.getDistanceMeters()) / 1000));
} else {
// FIXME isn't totalDistance in meters? Check this
elevationLabel.setText(String.format("%.3f",
(totalDistance - t.getDistanceMiles()) / 1000));
}
break;
case RouteReader.SLOPE:
elevationLabel.setText(String.format("%.0f", t.getElevation()));
slopeLabel.setText(String.format("%.1f", t.getGradient()));
break;
}
break;
case CADENCE:
int cadence = (Integer) o;
if (current != null) {
int i = current.isCadenceInRange(cadence);
if (i < 0) {
cadenceLabel.setForeground(skyBlue);
cadenceLabel.setText("" + cadence);
} else if (i > 0) {
cadenceLabel.setForeground(Color.RED);
cadenceLabel.setText("" + cadence);
} else {
cadenceLabel.setForeground(Color.WHITE);
cadenceLabel.setText("" + cadence);
}
} else {
cadenceLabel.setText("" + cadence);
}
break;
case HEARTRATE:
int heartRate = (Integer) o;
if (current != null) {
int i = current.isHRInRange(heartRate);
if (i < 0) {
hrLabel.setForeground(skyBlue);
hrLabel.setText("" + heartRate);
} else if (i > 0) {
hrLabel.setForeground(Color.RED);
hrLabel.setText("" + heartRate);
} else {
hrLabel.setForeground(Color.WHITE);
hrLabel.setText("" + heartRate);
}
} else {
hrLabel.setText(Integer.toString(heartRate));
}
break;
case TRAININGITEM:
current = (TrainingItem) o;
if (current != null) {
slopeLabel.setText("" + current.getPower());
}
break;
case GPXLOAD:
current = null;
// code to see if we are registered
if (!userPrefs.isRegistered() && (userPrefs.getEvalTime()) <= 0) {
logger.info("Out of time " + userPrefs.getEvalTime());
JOptionPane.showMessageDialog(this,
userPrefs.getString("trial_expired"),
userPrefs.getString("warning"),
JOptionPane.WARNING_MESSAGE);
userPrefs.shutDown();
System.exit(0);
}
RouteReader routeData = (RouteReader) o;
type = routeData.routeType();
switch (type) {
case RouteReader.POWER:
slopeText.setText(userPrefs.getString("target_power"));
levelText.setText(userPrefs.getString("distance_left"));
break;
case RouteReader.SLOPE:
slopeText.setText(userPrefs.getString("slope") + " %");
levelText.setText(userPrefs.getString("altitude"));
break;
}
totalDistance = routeData.getDistanceMeters();
startTime = 0;
speedLabel.setText("0.0");
powerLabel.setText("0");
cadenceLabel.setText("0");
hrLabel.setText("0");
distanceLabel.setText("0.0");
break;
case START:
powerLabel.setForeground(Color.WHITE);
initLabels(userPrefs.isMetric());
}
}
}