/* 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.power.Power; /** * Digital odometer. Used when no ANT+ stick detected. * * @author David George (c) Copyright 2013 * @date 19 June 2013 */ public class Odometer extends JPanel implements MessageCallback { private static final long serialVersionUID = -7939830514817673972L; private JLabel speedText; private JLabel distText; private JLabel slopeText; private JLabel levelText; private JLabel resistanceText; private JLabel speedLabel; private JLabel vspeedLabel; private JLabel distanceLabel; private JLabel elevationLabel; private JLabel slopeLabel; private JLabel resistanceLabel; private JLabel powerLabel; private JLabel chronoLabel; // i18n labels private final JLabel pwrText; private final JLabel chronoText; private int type = RouteReader.SLOPE; private static Logger logger = LogManager.getLogger("Odometer"); private final Color textColor = new Color(240, 244, 112); private static final int style1 = Font.CENTER_BASELINE; private static final Font font1 = new Font("Arial", style1, 13); private static final int style = Font.BOLD | Font.ITALIC; private static final Font font = new Font("Arial", style, 30); private DateFormat timeFormat; private long startTime = 0; private double totalDistance = 0; Power power; private static final double KMTOMILES = 1.609344; private final UserPreferences userPrefs = UserPreferences.INSTANCE; public Odometer() { super(); timeFormat = new SimpleDateFormat("HH:mm:ss"); timeFormat.setTimeZone(TimeZone.getTimeZone("GMT")); setBackground(Color.BLACK); MigLayout layout = new MigLayout("fillx", "[center]", "[][shrink 0]"); this.setLayout(layout); // Current Speed #1 speedText = new JLabel(); speedText.setFont(font1); speedText.setForeground(textColor); add(speedText); if (userPrefs.isVirtualPower()) { // Virtual Speed #1 JLabel vspeedText = new JLabel(); vspeedText.setFont(font1); vspeedText.setForeground(textColor); vspeedText.setText(userPrefs.getString("trainer_speed")); add(vspeedText); } // Distance #2 distText = new JLabel(); distText.setFont(font1); distText.setForeground(textColor); add(distText); // Power #3 pwrText = new JLabel(); pwrText.setFont(font1); pwrText.setForeground(textColor); add(pwrText); // Roller Resistance #4 resistanceText = new JLabel(); resistanceText.setFont(font1); resistanceText.setForeground(textColor); add(resistanceText); // Slope #5 slopeText = new JLabel(); slopeText.setFont(font1); slopeText.setForeground(textColor); add(slopeText); // Altitude #6 levelText = new JLabel(); levelText.setFont(font1); levelText.setForeground(textColor); add(levelText); // Chrono #7 chronoText = new JLabel(); chronoText.setFont(font1); chronoText.setForeground(textColor); add(chronoText, "Wrap"); // Variables // #1 speedLabel = new JLabel(); speedLabel.setFont(font); speedLabel.setText("0.0"); speedLabel.setForeground(Color.LIGHT_GRAY); add(speedLabel); if (userPrefs.isVirtualPower()) { // #2 vspeedLabel = new JLabel(); vspeedLabel.setFont(font); vspeedLabel.setText("0"); vspeedLabel.setForeground(Color.LIGHT_GRAY); add(vspeedLabel); } // #3 distanceLabel = new JLabel(); distanceLabel.setFont(font); distanceLabel.setText("0.0"); distanceLabel.setForeground(Color.LIGHT_GRAY); add(distanceLabel); // #4 powerLabel = new JLabel(); powerLabel.setFont(font); powerLabel.setText("0"); powerLabel.setForeground(Color.LIGHT_GRAY); add(powerLabel); // #5 resistanceLabel = new JLabel(); resistanceLabel.setFont(font); resistanceLabel.setText("0"); resistanceLabel.setForeground(Color.LIGHT_GRAY); add(resistanceLabel); // #6 slopeLabel = new JLabel(); slopeLabel.setFont(font); slopeLabel.setText("0.0"); slopeLabel.setForeground(Color.LIGHT_GRAY); add(slopeLabel); // #7 elevationLabel = new JLabel(); elevationLabel.setFont(font); elevationLabel.setForeground(Color.LIGHT_GRAY); elevationLabel.setText("0"); add(elevationLabel); // #8 chronoLabel = new JLabel(); chronoLabel.setFont(font); chronoLabel.setForeground(Color.LIGHT_GRAY); add(chronoLabel); chronoLabel.setText("00:00:00"); doText(); MessageBus.INSTANCE.register(Messages.SPEED, this); MessageBus.INSTANCE.register(Messages.GPXLOAD, this); MessageBus.INSTANCE.register(Messages.START, this); MessageBus.INSTANCE.register(Messages.LOCALE, this); } @Override public void callback(Messages message, Object o) { switch (message) { case SPEED: Telemetry t = (Telemetry) o; if (startTime == 0) { startTime = t.getTime(); } // Power powerLabel.setText("" + t.getPower()); // Resistance resistanceLabel.setText("" + t.getResistance()); // Speed & Distance if (userPrefs.isMetric()) { speedLabel.setText(String.format("%.1f", t.getSpeedKMH())); if (userPrefs.isVirtualPower()) { vspeedLabel.setText(String.format("%.1f", t.getTrainerSpeed())); } distanceLabel.setText(String.format("%.3f", t.getDistanceKM())); } else { speedLabel.setText(String.format("%.1f", t.getSpeedMPH())); distanceLabel.setText(String.format("%.3f", t.getDistanceMiles())); // need to round up or down if (userPrefs.isVirtualPower()) { vspeedLabel.setText(String.format("%.1f", (t.getTrainerSpeed() / KMTOMILES))); } } chronoLabel.setText(timeFormat.format(new Date(t.getTime() - startTime))); switch (type) { case RouteReader.POWER: if (userPrefs.isMetric()) { elevationLabel.setText(String.format("%.1f", (totalDistance / 1000) - t.getDistanceKM())); } else { elevationLabel.setText(String.format("%.1f", ((totalDistance / 1000) - t.getDistanceMiles()))); } break; case RouteReader.SLOPE: elevationLabel.setText(String.format("%.0f", t.getElevation())); slopeLabel.setText(String.format("%.1f", t.getGradient())); break; }// switch if (type == RouteReader.SLOPE) { break; } break; case GPXLOAD: RouteReader routeData = (RouteReader) o; type = routeData.routeType(); switch (type) { case RouteReader.POWER: levelText .setText(userPrefs.getString("distance_left")); slopeText.setVisible(false); slopeLabel.setVisible(false); break; case RouteReader.SLOPE: levelText.setText(userPrefs.getString("altitude")); slopeText.setVisible(true); slopeLabel.setVisible(true); break; } totalDistance = routeData.getDistanceMeters(); startTime = 0; speedLabel.setText("0.0"); powerLabel.setText("0"); if (userPrefs.getResistance() == userPrefs.getPowerProfile().getResitanceLevels()) { // AUTO resistanceLabel.setVisible(true); resistanceText.setVisible(true); resistanceLabel.setText("1"); } else { resistanceLabel.setVisible(false); resistanceText.setVisible(false); } distanceLabel.setText("0.0"); break; case START: // 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); } //doText(); break; case LOCALE: doText(); break; } } /* * Setup button text, makes it easy to update if locale is changed */ private void doText() { pwrText.setText(userPrefs.getString("power")); resistanceText.setText(userPrefs.getString("resistance")); slopeText.setText(userPrefs.getString("slope") + " %"); levelText.setText(userPrefs.getString("altitude")); chronoText.setText(userPrefs.getString("stopwatch")); if (userPrefs.isMetric()) { 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)"); } } }