diff --git a/.classpath b/.classpath
index 5c59d7a..ad3f9d4 100644
--- a/.classpath
+++ b/.classpath
@@ -2,6 +2,6 @@
-
+
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 3a21537..8000cd6 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,11 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
-org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
-org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
-org.eclipse.jdt.core.compiler.source=1.8
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/src/com/flaremicro/flaretv/visualforecast/RenderPanel.java b/src/com/flaremicro/flaretv/visualforecast/RenderPanel.java
index 6531260..3f853cb 100644
--- a/src/com/flaremicro/flaretv/visualforecast/RenderPanel.java
+++ b/src/com/flaremicro/flaretv/visualforecast/RenderPanel.java
@@ -3,24 +3,29 @@ package com.flaremicro.flaretv.visualforecast;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
-import java.awt.FontFormatException;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
-import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.awt.image.BufferedImage;
import java.awt.image.VolatileImage;
-import java.io.IOException;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
import java.util.Calendar;
-import java.util.concurrent.locks.LockSupport;
import javax.swing.JPanel;
-import com.flaremicro.flaretv.visualforecast.icons.IconProvider;
+import static com.flaremicro.flaretv.visualforecast.graphics.RenderConstants.*;
-public class RenderPanel extends JPanel implements Runnable {
+import com.flaremicro.flaretv.visualforecast.flavour.DayForecastFlavour;
+import com.flaremicro.flaretv.visualforecast.flavour.Flavour;
+import com.flaremicro.flaretv.visualforecast.forecast.MockForecastProvider;
+import com.flaremicro.flaretv.visualforecast.graphics.DrawingUtil;
+import com.flaremicro.flaretv.visualforecast.graphics.FontManager;
+import com.flaremicro.flaretv.visualforecast.interfaces.Tickable;
+
+public class RenderPanel extends JPanel implements Tickable, ComponentListener {
/**
*
@@ -29,65 +34,30 @@ public class RenderPanel extends JPanel implements Runnable {
private VolatileImage frameBuffer = null;
- /**
- * Create the panel.
- */
-
- private Color backgroundPurple = new Color(0x2b29b3);
- private Color backgroundOrange = new Color(0xff8c00);
- private Color backgroundBlue = new Color(0x394aa8);
-
private Font font = null;
- float fontMult = 20F;
+ private Flavour currentFlavour = new DayForecastFlavour();
- private int animationTick = 0;
+ private int iconAnimationTicks = 0;
+ private long ticks = 0;
- private String[] testString;
+ private Rectangle redrawBound = new Rectangle(0, 0, 1, 1);
+
+ private String currentTown = "";
+ private String currentForecast = "";
public RenderPanel() {
- try
- {
- font = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("/Star4000.ttf"));
- }
- catch (FontFormatException e)
- {
- e.printStackTrace();
- }
- catch (IOException e)
- {
- e.printStackTrace();
- }
- testString = "".split("\n");
- new Thread(this).start();
+ this.addComponentListener(this);
+ font = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf"));
+ currentFlavour.initFlavour(this, MockForecastProvider.provideMockForecast(), ticks, iconAnimationTicks);
+ new Thread(new TickThread(this, 30)).start();
}
- private static final int W = 640, H = 480;
- private static final int INFOBAR_HEIGHT = 80;
- private static final int TOPBAR_HEIGHT = 80;
- private static final int MAINBAR_HEIGHT = H - INFOBAR_HEIGHT - TOPBAR_HEIGHT;
-
- private static final int HEADERBAR_Y = 20;
- private static final double HEADERBAR_SHEAR = 0.2;
- private static final int HEADERBAR_OFFSET = 20;
- private static final int HEADERBAR_WIDTH = 400 + HEADERBAR_OFFSET;
- private static final int HEADERBAR_HEIGHT = TOPBAR_HEIGHT - HEADERBAR_Y;
-
- private static final int TIMEBAR_Y = 40;
- private static final int TIMEBAR_OFFSET = 20;
- private static final int TIMEBAR_WIDTH = 230 + HEADERBAR_OFFSET;
- private static final int TIMEBAR_HEIGHT = TOPBAR_HEIGHT - TIMEBAR_Y;
-
- private static final int STROKE_WIDTH = 2;
- private static final int STROKE_OFFSET = STROKE_WIDTH / 2;
-
- private static final DateFormat DATE_FORMAT = new SimpleDateFormat("MMMM d");
- private static final DateFormat TIME_FORMAT = new SimpleDateFormat("hh:mm:ss a");
-
- public Graphics2D prepareFrameBuffer() {
+ private Graphics2D prepareFrameBuffer() {
GraphicsConfiguration gc = this.getGraphicsConfiguration();
- if (frameBuffer == null || frameBuffer.validate(gc) != VolatileImage.IMAGE_INCOMPATIBLE)
+ if (frameBuffer == null || frameBuffer.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE)
{
+ System.out.println("new image req'd");
frameBuffer = gc.createCompatibleVolatileImage(W, H);
}
return (Graphics2D) frameBuffer.getGraphics();
@@ -115,29 +85,41 @@ public class RenderPanel extends JPanel implements Runnable {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = prepareFrameBuffer();
- if (font == null)
- font = g2d.getFont();
+
+ drawMainRegion(g2d);
+ if (currentFlavour != null)
+ {
+ if (this.getBounds().equals(g.getClipBounds()))
+ this.currentFlavour.drawFlavour(this, g2d, ticks, iconAnimationTicks);
+ if (g.getClipBounds() != null)
+ this.currentFlavour.drawBoundLimitedFlavour(this, g2d, g.getClipBounds(), ticks, iconAnimationTicks);
+ }
+ g2d.dispose();
+ g.drawImage(frameBuffer, 0, 0, getWidth(), getHeight(), this);
+ }
+
+ private void drawMainRegion(Graphics2D g2d) {
g2d.setFont(font.deriveFont(24F));
g2d.setStroke(new BasicStroke(2));
- g2d.setColor(this.backgroundPurple);
+ g2d.setColor(BG_PURPLE);
g2d.fillRect(0, 0, W, TOPBAR_HEIGHT);
- g2d.setPaint(new GradientPaint(0, HEADERBAR_Y, backgroundOrange, 0, HEADERBAR_Y + (HEADERBAR_HEIGHT + 10), backgroundPurple));
+ g2d.setPaint(new GradientPaint(0, HEADERBAR_Y, BG_OORANGE, 0, HEADERBAR_Y + (HEADERBAR_HEIGHT + 10), BG_PURPLE));
g2d.shear(HEADERBAR_SHEAR, 0);
g2d.fillRect(-HEADERBAR_OFFSET, HEADERBAR_Y, HEADERBAR_WIDTH, HEADERBAR_HEIGHT);
- g2d.setPaint(new GradientPaint(0, HEADERBAR_Y, backgroundPurple.brighter().brighter().brighter(), 0, HEADERBAR_Y + (HEADERBAR_HEIGHT + 10), backgroundPurple));
+ g2d.setPaint(new GradientPaint(0, HEADERBAR_Y, BG_PURPLE.brighter().brighter().brighter(), 0, HEADERBAR_Y + (HEADERBAR_HEIGHT + 10), BG_PURPLE));
g2d.fillRect(W - TIMEBAR_WIDTH + TIMEBAR_OFFSET, TIMEBAR_Y, TIMEBAR_WIDTH, TIMEBAR_HEIGHT);
g2d.shear(-HEADERBAR_SHEAR, 0);
- g2d.setPaint(new GradientPaint(0, TOPBAR_HEIGHT, backgroundPurple, 0, MAINBAR_HEIGHT, backgroundOrange));
+ g2d.setPaint(new GradientPaint(0, TOPBAR_HEIGHT, BG_PURPLE, 0, MAINBAR_HEIGHT, BG_OORANGE));
g2d.fillRect(0, TOPBAR_HEIGHT, W, MAINBAR_HEIGHT);
g2d.fillRect(0, TOPBAR_HEIGHT, W, MAINBAR_HEIGHT);
- g2d.setColor(this.backgroundBlue);
+ g2d.setColor(BG_BLUE);
g2d.fillRect(0, H - INFOBAR_HEIGHT, W, INFOBAR_HEIGHT);
g2d.setColor(Color.DARK_GRAY);
@@ -146,120 +128,104 @@ public class RenderPanel extends JPanel implements Runnable {
g2d.setColor(Color.WHITE);
g2d.drawLine(0, H - INFOBAR_HEIGHT + STROKE_WIDTH + STROKE_OFFSET, W, H - INFOBAR_HEIGHT + STROKE_WIDTH + STROKE_OFFSET);
- drawGradientRect(g2d, 60, TOPBAR_HEIGHT, W - 120, MAINBAR_HEIGHT, 20, backgroundBlue.brighter(), backgroundBlue.darker());
- g2d.setColor(backgroundBlue.brighter());
- g2d.drawRect(60 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET, W - 120 - STROKE_WIDTH, MAINBAR_HEIGHT - STROKE_WIDTH);
// g2d.setColor(Color.GRAY);
// g2d.drawRect(60, TOPBAR_HEIGHT+2, W-120, MAINBAR_HEIGHT-4);
String dateString = DATE_FORMAT.format(System.currentTimeMillis()) + getDayOfMonthSuffix();
String timeString = TIME_FORMAT.format(System.currentTimeMillis());
- // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- // RenderingHints.VALUE_ANTIALIAS_ON);
- drawOutlinedString(g2d, 60, HEADERBAR_Y + 18, "7 Day Forecast", Color.WHITE, Color.BLACK, 1);
+ DrawingUtil.drawOutlinedString(g2d, 60, HEADERBAR_Y + 18, currentForecast, Color.WHITE, Color.BLACK, 2);
int sw = g2d.getFontMetrics().stringWidth(dateString);
- drawOutlinedString(g2d, W - sw - 60, TIMEBAR_Y + 18, dateString, Color.WHITE, Color.BLACK, 1);
+ DrawingUtil.drawOutlinedString(g2d, W - sw - 60, TIMEBAR_Y + 18, dateString, Color.WHITE, Color.BLACK, 2);
sw = g2d.getFontMetrics().stringWidth(timeString);
- drawOutlinedString(g2d, W - sw - 60, TIMEBAR_Y + 36, timeString, Color.WHITE, Color.BLACK, 1);
+ DrawingUtil.drawOutlinedString(g2d, W - sw - 60, TIMEBAR_Y + 36, timeString, Color.WHITE, Color.BLACK, 2);
g2d.setFont(font.deriveFont(36F));
- drawOutlinedString(g2d, 60, HEADERBAR_Y + 52, "Burnaby, BC", Color.YELLOW, Color.BLACK, 2);
+ DrawingUtil.drawOutlinedString(g2d, 60, HEADERBAR_Y + 52, currentTown, Color.YELLOW, Color.BLACK, 2);
- int w2 = g2d.getFontMetrics().stringWidth("EXTREME WEATHER ADVISORY");
- drawOutlinedString(g2d, (W >> 1) - (w2 >> 1), TOPBAR_HEIGHT + 48, "EXTREME WEATHER ADVISORY", Color.RED, Color.BLACK, 2);
-
- g2d.setFont(font.deriveFont(30F));
- for (int i = 0; i < testString.length; i++)
- {
- drawOutlinedString(g2d, 90, TOPBAR_HEIGHT + 78 + 25 * i, testString[i], Color.WHITE, Color.BLACK, 1);
- }
-
- // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
- // RenderingHints.VALUE_ANTIALIAS_ON);
-
- IconProvider.drawIcon(g2d, IconProvider.SUN, 80, 220, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.CLOUD, 160, 220, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.PARTLY_CLOUDY, 160 + 80, 220, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.CLOUDY_CLOUDY, 160 + 160, 220, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.SCATTERD_SHOWERS, 160 + 160 + 80, 220, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.SNOWFLAKE, 160 + 160 + 160, 220, 80, animationTick);
-
- IconProvider.drawIcon(g2d, IconProvider.BLIZZARD, 80, 140, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.SNOW, 160, 140, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.FREEZING_RAIN, 160 + 80, 140, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.RAIN_SNOW, 160 + 160, 140, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.LIGHTNING_OVERLAY, 160 + 160+80, 140, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.LIGHTNING_STORM, 160 + 160+160, 140, 80, animationTick);
-
- IconProvider.drawIcon(g2d, IconProvider.RAIN_LIGHTEST, 80, 300, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.RAIN_LIGHT, 160, 300, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.RAIN, 160 + 80, 300, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.RAIN_HEAVY, 160 + 160, 300, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.RAIN_HEAVIEST, 160 + 160 + 80, 300, 80, animationTick);
- IconProvider.drawIcon(g2d, IconProvider.RAIN_VANCOUVER, 160 + 160 + 160, 300, 80, animationTick);
-
- g2d.dispose();
- g.drawImage(frameBuffer, 0, 0, getWidth(), getHeight(), this);
- }
-
- public void drawGradientRect(Graphics2D g, int x, int y, int w, int h, int borderWidth, Color innerColor, Color outerColor) {
-
- g.setColor(innerColor);
- g.fillRect(x, y, w, h);
-
- g.setPaint(new GradientPaint(x, 0, outerColor, x + borderWidth, 0, innerColor));
- g.fillRect(x, y, borderWidth, h);
-
- g.setPaint(new GradientPaint(x + w - borderWidth, 0, innerColor, x + w, 0, outerColor));
- g.fillRect(x + w - borderWidth, y, borderWidth, h);
-
- g.setPaint(new GradientPaint(0, y, outerColor, 0, y + borderWidth, innerColor));
- g.setClip(new Polygon(new int[] { x, x + w, x + w - borderWidth, x + borderWidth }, new int[] { y, y, y + borderWidth, y + borderWidth }, 4));
- g.fillRect(x, y, w, borderWidth);
-
- g.setClip(new Polygon(new int[] { x, x + w, x + w - borderWidth, x + borderWidth }, new int[] { y + h, y + h, y + h - borderWidth, y + h - borderWidth }, 4));
- g.setPaint(new GradientPaint(0, y + h - borderWidth, innerColor, 0, y + h, outerColor));
- g.fillRect(x, y + h - borderWidth, w, borderWidth);
-
- g.setClip(null);
+ g2d.setFont(font.deriveFont(26F));
+ DrawingUtil.drawOutlinedString(g2d, -20, H - INFOBAR_HEIGHT + 30, "Welcome to WeatherBC! Stay tuned for your long range forcast", Color.WHITE, Color.BLACK, 2);
}
- public void drawOutlinedString(Graphics2D g2d, int x, int y, String text, Color textColor, Color outline, int outlineSize) {
- g2d.setColor(outline);
- for (int i = 1; i <= outlineSize; i++)
+ public void tick() {
+ this.ticks++;
+ if (ticks / 3.75F > this.iconAnimationTicks)
{
- g2d.drawString(text, x + i, y);
- g2d.drawString(text, x - i, y);
- g2d.drawString(text, x, y + i);
- g2d.drawString(text, x, y - i);
- g2d.drawString(text, x + i, y + i);
- g2d.drawString(text, x - i, y - i);
- g2d.drawString(text, x - i, y + i);
- g2d.drawString(text, x + i, y - i);
+ this.iconAnimationTicks++;
+ //Clock and icon animations, should use repaint regions later
+ if (getWidth() > 0 && getHeight() > 0)
+ {
+ repaint(this.redrawBound);
+ }
}
+ if (this.currentFlavour != null)
+ this.currentFlavour.tick(this, ticks, iconAnimationTicks);
+ }
- g2d.setColor(textColor);
- g2d.drawString(text, x, y);
- /*
- * AffineTransform transform = g2d.getTransform();
- * transform.translate(x, y); g2d.transform(transform);
- * g2d.setColor(outline); FontRenderContext frc =
- * g2d.getFontRenderContext(); TextLayout tl = new TextLayout(text,
- * g2d.getFont(), frc); Shape shape = tl.getOutline(null);
- * g2d.setStroke(new BasicStroke(outlineSize)); g2d.draw(shape);
- * g2d.setColor(textColor); g2d.fill(shape);
- */
+ public BufferedImage getSnapshot() {
+ return frameBuffer.getSnapshot();
+ }
+
+ public void addRedrawBound(int x, int y, int w, int h) {
+ float wScale = getWidth() / (float) W;
+ float hScale = getHeight() / (float) H;
+ Rectangle rect = new Rectangle((int) (x * wScale), (int) (y * hScale), (int) (w * wScale), (int) (h * hScale));
+ if (redrawBound == null)
+ this.redrawBound = new Rectangle((int) (x * wScale), (int) (y * hScale), (int) (w * wScale), (int) (h * hScale));
+ else this.redrawBound.add(rect);
}
@Override
+ public void componentResized(ComponentEvent e) {
+ this.redrawBound = null;
+ addRedrawBound(W - TIMEBAR_WIDTH + TIMEBAR_OFFSET, TIMEBAR_Y, TIMEBAR_WIDTH, TIMEBAR_HEIGHT);
+ if (this.currentFlavour != null)
+ this.currentFlavour.redrawRegionlost(this);
+ }
+
+ @Override
+ public void componentMoved(ComponentEvent e) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void componentShown(ComponentEvent e) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void componentHidden(ComponentEvent e) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void nextFlavour() {
+ this.currentFlavour = new DayForecastFlavour();
+ this.currentFlavour.initFlavour(this, MockForecastProvider.provideMockForecast(), ticks, iconAnimationTicks);
+ }
+
+ public void setCurrentTown(String currentTown){
+ this.currentTown = currentTown;
+ }
+
+ public void setCurrentForecast(String currentForecast){
+ this.currentForecast = currentForecast;
+ }
+
+ public void setFullRepaint() {
+ repaint();
+ }
+
+ /*@Override
public void run() {
while (true)
{
- this.animationTick++;
+ this.iconAnimationTicks++;
repaint();
LockSupport.parkNanos(125000000);
}
- }
+ }*/
}
diff --git a/src/com/flaremicro/flaretv/visualforecast/SmallTextInfo.java b/src/com/flaremicro/flaretv/visualforecast/SmallTextInfo.java
deleted file mode 100644
index 56eb452..0000000
--- a/src/com/flaremicro/flaretv/visualforecast/SmallTextInfo.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.flaremicro.flaretv.visualforecast;
-
-import javax.swing.JFrame;
-import javax.swing.JPanel;
-import javax.swing.border.EmptyBorder;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import javax.swing.JSpinner;
-import javax.swing.SpinnerNumberModel;
-
-public class SmallTextInfo extends JFrame {
-
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- private JPanel contentPane;
-
- /**
- * Create the frame.
- */
- public SmallTextInfo(RenderPanel rp) {
- setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- setBounds(100, 100, 295, 93);
- contentPane = new JPanel();
- contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
- setContentPane(contentPane);
- contentPane.setLayout(null);
-
- JSpinner spinner = new JSpinner();
- spinner.setModel(new SpinnerNumberModel(new Float(rp.fontMult), null, null, new Float(0.5F)));
- spinner.setBounds(12, 12, 255, 22);
- spinner.addChangeListener(new ChangeListener(){
-
- @Override
- public void stateChanged(ChangeEvent e) {
- rp.fontMult = (Float)spinner.getValue();
- rp.repaint();
- }
-
- });
- contentPane.add(spinner);
- }
-}
diff --git a/src/com/flaremicro/flaretv/visualforecast/TickThread.java b/src/com/flaremicro/flaretv/visualforecast/TickThread.java
index b9037db..fdd3964 100644
--- a/src/com/flaremicro/flaretv/visualforecast/TickThread.java
+++ b/src/com/flaremicro/flaretv/visualforecast/TickThread.java
@@ -1,5 +1,7 @@
package com.flaremicro.flaretv.visualforecast;
+import java.util.concurrent.locks.LockSupport;
+
import com.flaremicro.flaretv.visualforecast.interfaces.Tickable;
public class TickThread implements Runnable {
@@ -7,12 +9,16 @@ public class TickThread implements Runnable {
private boolean running = true;
private final long sleepNanos;
- private long nextTick = 0;
+ //private long nextTick = 0;
TickThread(Tickable tickable, long sleepNanos) {
this.tickable = tickable;
this.sleepNanos = sleepNanos;
}
+
+ TickThread(Tickable tickable, int ticksPerSecond) {
+ this(tickable, (long) ((1/(double)ticksPerSecond) * 1000000000L));
+ }
public void end() {
this.running = false;
@@ -20,7 +26,7 @@ public class TickThread implements Runnable {
public void run() {
while (running) {
- while(System.nanoTime() < nextTick)
+ /*while(System.nanoTime() < nextTick)
{
try
{
@@ -32,12 +38,13 @@ public class TickThread implements Runnable {
}
}
nextTick = System.nanoTime() + sleepNanos;
+ tickable.tick();*/
+ long nanosLost = System.nanoTime();
tickable.tick();
- /*long nanosLost = System.nanoTime();
- panel.tick();
nanosLost -= System.nanoTime();
- if(sleepNanos+nanosLost > 0)
- LockSupport.parkNanos(sleepNanos+nanosLost);*/
+ //Unnecessary conditional?
+ //if(sleepNanos+nanosLost > 0)
+ LockSupport.parkNanos(sleepNanos+nanosLost);
}
}
}
\ No newline at end of file
diff --git a/src/com/flaremicro/flaretv/visualforecast/flavour/DayForecastFlavour.java b/src/com/flaremicro/flaretv/visualforecast/flavour/DayForecastFlavour.java
new file mode 100644
index 0000000..546a3ae
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/flavour/DayForecastFlavour.java
@@ -0,0 +1,172 @@
+package com.flaremicro.flaretv.visualforecast.flavour;
+
+import static com.flaremicro.flaretv.visualforecast.graphics.RenderConstants.MAINBAR_HEIGHT;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.util.Calendar;
+import java.util.Locale;
+
+import com.flaremicro.flaretv.visualforecast.RenderPanel;
+import com.flaremicro.flaretv.visualforecast.forecast.DayForecast;
+import com.flaremicro.flaretv.visualforecast.forecast.ForecastDetails;
+import com.flaremicro.flaretv.visualforecast.forecast.TownForecast;
+import com.flaremicro.flaretv.visualforecast.forecast.ValueCheck;
+import com.flaremicro.flaretv.visualforecast.graphics.DrawingUtil;
+import com.flaremicro.flaretv.visualforecast.graphics.FontManager;
+import com.flaremicro.flaretv.visualforecast.graphics.RenderConstants;
+import com.flaremicro.flaretv.visualforecast.icons.IconProvider;
+
+public class DayForecastFlavour implements Flavour {
+ private int dayOffset = 0;
+ private Font font;
+ private Font smallFont;
+ private ForecastDetails details;
+ private TownForecast currentTown = null;
+ private int townIndex;
+
+ private BufferedImage lastBound = null;
+
+ private int ticksBeforeChange = 200;
+
+ public DayForecastFlavour() {
+ font = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf"));
+ smallFont = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000 Small.ttf"));
+ }
+
+ @Override
+ public void tick(RenderPanel renderer, long ticks, int iconTicks) {
+ ticksBeforeChange--;
+ if (ticksBeforeChange < 0)
+ {
+ ticksBeforeChange = 200;
+ dayOffset = dayOffset + 4;
+ if (dayOffset >= 8)
+ {
+ dayOffset = 0;
+ townIndex++;
+ if (townIndex >= details.getTownForecast().length)
+ {
+ renderer.nextFlavour();
+ }
+ else
+ {
+ currentTown = details.getTownForecast()[townIndex];
+ renderer.setCurrentTown(currentTown.getTownName());
+ }
+ }
+ renderer.setFullRepaint();
+ }
+ }
+
+ @Override
+ public void initFlavour(RenderPanel renderer, ForecastDetails details, long ticks, int iconTicks) {
+ this.details = details;
+ renderer.setCurrentForecast("7 Day Forecast");
+ if (details == null || details.getTownForecast() == null || details.getTownForecast().length <= 0)
+ this.details = null;
+ else
+ {
+ townIndex = 0;
+ currentTown = details.getTownForecast()[townIndex];
+ renderer.setCurrentTown(currentTown.getTownName());
+ }
+ redrawRegionlost(renderer);
+ }
+
+ private String getDay(int offset) {
+ if (offset == 0)
+ return "Today";
+ Calendar cal = Calendar.getInstance();
+ cal.add(Calendar.HOUR, offset * 24);
+ return cal.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.US);
+ }
+
+ @Override
+ public void drawFlavour(RenderPanel renderer, Graphics2D g2d, long ticks, int iconTicks) {
+ if (details == null || currentTown == null || currentTown.getDayForecast() == null || currentTown.getDayForecast().length <= 0)
+ {
+ DrawingUtil.drawGradientRect(g2d, RenderConstants.SIDE_OFFSET + 80, RenderConstants.TOPBAR_HEIGHT + 90, RenderConstants.W - RenderConstants.SIDE_OFFSET * 2 - 160, (RenderConstants.TOPBAR_HEIGHT + 20), 10, new Color(0x220088), new Color(0x110055));
+ g2d.setFont(font.deriveFont(26F));
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + 60 + (RenderConstants.W - RenderConstants.SIDE_OFFSET * 2 - 120) / 2 - (g2d.getFontMetrics().stringWidth("Forcast data") / 2), RenderConstants.TOPBAR_HEIGHT + 130, "Forecast data", Color.WHITE, Color.BLACK, 2);
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + 60 + (RenderConstants.W - RenderConstants.SIDE_OFFSET * 2 - 120) / 2 - (g2d.getFontMetrics().stringWidth("temporarily unavailable") / 2), RenderConstants.TOPBAR_HEIGHT + 160, "temporarily unavailable", Color.WHITE, Color.BLACK, 2);
+
+ }
+ else
+ {
+ for (int i = 0; i < Math.min(4, currentTown.getDayForecast().length - this.dayOffset); i++)
+ {
+
+ DayForecast forecast = currentTown.getDayForecast()[i+this.dayOffset];
+ g2d.setColor(RenderConstants.BG_BLUE.brighter().brighter());
+ g2d.fillRect(RenderConstants.SIDE_OFFSET + 131 * i, RenderConstants.TOPBAR_HEIGHT + 15, 127, MAINBAR_HEIGHT - 30);
+
+ g2d.setPaint(new GradientPaint(0, RenderConstants.TOPBAR_HEIGHT + 40, new Color(0x7777FF), 0, (RenderConstants.TOPBAR_HEIGHT + 40) + MAINBAR_HEIGHT - 60, new Color(0x0000BB)));
+ g2d.fillRoundRect(RenderConstants.SIDE_OFFSET + 5 + 131 * i, RenderConstants.TOPBAR_HEIGHT + 20, 117, MAINBAR_HEIGHT - 40, 10, 10);
+ g2d.setColor(Color.BLACK);
+ g2d.drawRoundRect(RenderConstants.SIDE_OFFSET + 5 + 131 * i, RenderConstants.TOPBAR_HEIGHT + 20, 117, MAINBAR_HEIGHT - 40, 10, 10);
+ g2d.drawRect(RenderConstants.SIDE_OFFSET + 131 * i, RenderConstants.TOPBAR_HEIGHT + 15, 127, MAINBAR_HEIGHT - 30);
+
+ String day = getDay(i + dayOffset);
+
+ g2d.setFont(font.deriveFont(26F));
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + (131 * i) + (127 / 2) - (g2d.getFontMetrics().stringWidth(day) / 2), RenderConstants.TOPBAR_HEIGHT + 50, day, Color.WHITE, Color.BLACK, 2);
+
+ String statLine1;
+ String statLine2;
+ if(ValueCheck.valueNoData(forecast.weatherLine1))
+ {
+ statLine1 = "MISSING";
+ statLine2 = "DATA";
+ }
+ else
+ {
+ statLine1 = forecast.weatherLine1;
+ statLine2 = ValueCheck.valueNoData(forecast.weatherLine2) ? "" : forecast.weatherLine2;
+ }
+ FontMetrics metrics = g2d.getFontMetrics();
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + (131 * i) + (127 / 2) - (metrics.stringWidth(statLine1) / 2), RenderConstants.TOPBAR_HEIGHT + 170, statLine1, Color.WHITE, Color.BLACK, 2);
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + (131 * i) + (127 / 2) - (metrics.stringWidth(statLine2) / 2), RenderConstants.TOPBAR_HEIGHT + 200, statLine2, Color.WHITE, Color.BLACK, 2);
+
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + (131 * i) + 30 - (metrics.stringWidth(String.valueOf(forecast.hiTemp)) >> 1), RenderConstants.TOPBAR_HEIGHT + 295, String.valueOf(forecast.hiTemp), Color.WHITE, Color.BLACK, 2);
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + (131 * i) + 92 - (metrics.stringWidth(String.valueOf(forecast.loTemp)) >> 1), RenderConstants.TOPBAR_HEIGHT + 295, String.valueOf(forecast.loTemp), Color.WHITE, Color.BLACK, 2);
+
+ g2d.setFont(smallFont.deriveFont(24F));
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + (131 * i) + 20, RenderConstants.TOPBAR_HEIGHT + 270, "Hi", Color.RED, Color.BLACK, 2);
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + (131 * i) + 82, RenderConstants.TOPBAR_HEIGHT + 270, "Lo", Color.CYAN, Color.BLACK, 2);
+
+ if(!ValueCheck.valueNoData(forecast.percipPercent))
+ {
+ String formattedPercent = String.format("%.2f%%", forecast.percipPercent);
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + (131 * i) + (127 / 2) - (g2d.getFontMetrics().stringWidth("Precip.") / 2), RenderConstants.TOPBAR_HEIGHT + 230, "Precip.", Color.YELLOW, Color.BLACK, 2);
+ DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + (131 * i) + (127 / 2) - (g2d.getFontMetrics().stringWidth(formattedPercent) / 2), RenderConstants.TOPBAR_HEIGHT + 245, formattedPercent, Color.WHITE, Color.BLACK, 2);
+ }
+ }
+ }
+ lastBound = renderer.getSnapshot().getSubimage(RenderConstants.SIDE_OFFSET, RenderConstants.TOPBAR_HEIGHT + 15, 524, MAINBAR_HEIGHT - 30);
+ lastBound.setAccelerationPriority(1);
+ }
+
+ @Override
+ public void drawBoundLimitedFlavour(RenderPanel renderer, Graphics2D g2d, Rectangle bounds, long ticks, int iconTicks) {
+ g2d.drawImage(lastBound, RenderConstants.SIDE_OFFSET, RenderConstants.TOPBAR_HEIGHT + 15, renderer);
+ if (details != null && currentTown != null && currentTown.getDayForecast() != null && currentTown.getDayForecast().length > 0)
+ {
+ for (int i = 0; i < Math.min(4, currentTown.getDayForecast().length - this.dayOffset); i++)
+ {
+ DayForecast forecast = currentTown.getDayForecast()[i+this.dayOffset];
+ IconProvider.drawIcon(g2d, IconProvider.INDEXED_ICONS[forecast.iconId & IconProvider.INDEXED_ICONS.length-1], RenderConstants.SIDE_OFFSET + (131 * i) + 24, RenderConstants.TOPBAR_HEIGHT + 60, 80, iconTicks);
+ }
+ }
+ }
+
+ @Override
+ public void redrawRegionlost(RenderPanel renderer) {
+ renderer.addRedrawBound(RenderConstants.SIDE_OFFSET + 24, RenderConstants.TOPBAR_HEIGHT + 60, 604, 84);
+ }
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/flavour/Flavour.java b/src/com/flaremicro/flaretv/visualforecast/flavour/Flavour.java
index eef212f..0f5ddab 100644
--- a/src/com/flaremicro/flaretv/visualforecast/flavour/Flavour.java
+++ b/src/com/flaremicro/flaretv/visualforecast/flavour/Flavour.java
@@ -1,5 +1,15 @@
package com.flaremicro.flaretv.visualforecast.flavour;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+
+import com.flaremicro.flaretv.visualforecast.RenderPanel;
+import com.flaremicro.flaretv.visualforecast.forecast.ForecastDetails;
+
public interface Flavour {
-
+ public void tick(RenderPanel renderer, long ticks, int iconTicks);
+ public void initFlavour(RenderPanel renderer, ForecastDetails details, long ticks, int iconTicks);
+ public void drawFlavour(RenderPanel renderer, Graphics2D g, long ticks, int iconTicks);
+ public void drawBoundLimitedFlavour(RenderPanel renderer, Graphics2D g, Rectangle bounds, long ticks, int iconTicks);
+ public void redrawRegionlost(RenderPanel renderer);
}
diff --git a/src/com/flaremicro/flaretv/visualforecast/flavour/TextFlavour.java b/src/com/flaremicro/flaretv/visualforecast/flavour/TextFlavour.java
new file mode 100644
index 0000000..2c0e82c
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/flavour/TextFlavour.java
@@ -0,0 +1,61 @@
+package com.flaremicro.flaretv.visualforecast.flavour;
+
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+
+import com.flaremicro.flaretv.visualforecast.RenderPanel;
+import com.flaremicro.flaretv.visualforecast.forecast.ForecastDetails;
+import com.flaremicro.flaretv.visualforecast.graphics.DrawingUtil;
+
+import static com.flaremicro.flaretv.visualforecast.graphics.RenderConstants.*;
+
+public class TextFlavour implements Flavour{
+
+ public TextFlavour(String title, String scrollText)
+ {
+ /*
+ int w2 = g2d.getFontMetrics().stringWidth("EXTREME WEATHER ADVISORY");
+ drawOutlinedString(g2d, (W >> 1) - (w2 >> 1), TOPBAR_HEIGHT + 48, "EXTREME WEATHER ADVISORY", Color.RED, Color.BLACK, 2);
+
+ g2d.setFont(font.deriveFont(30F));
+ for (int i = 0; i < testString.length; i++)
+ {
+ drawOutlinedString(g2d, 90, TOPBAR_HEIGHT + 78 + 25 * i, testString[i], Color.WHITE, Color.BLACK, 1);
+ }
+ */
+ }
+
+ @Override
+ public void tick(RenderPanel renderer, long ticks, int iconTicks) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void initFlavour(RenderPanel renderer, ForecastDetails details, long ticks, int iconTicks) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void drawFlavour(RenderPanel renderer, Graphics2D g2d, long ticks, int iconTicks) {
+ DrawingUtil.drawGradientRect(g2d, 60, TOPBAR_HEIGHT, W - 120, MAINBAR_HEIGHT, 20, BG_BLUE.brighter(), BG_BLUE.darker());
+ g2d.setColor(BG_BLUE.brighter());
+ g2d.drawRect(60 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET, W - 120 - STROKE_WIDTH, MAINBAR_HEIGHT - STROKE_WIDTH);
+
+ }
+
+ @Override
+ public void drawBoundLimitedFlavour(RenderPanel renderer, Graphics2D g2d, Rectangle bounds, long ticks, int iconTicks) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void redrawRegionlost(RenderPanel renderer) {
+ // TODO Auto-generated method stub
+
+ }
+
+
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/forecast/DayForecast.java b/src/com/flaremicro/flaretv/visualforecast/forecast/DayForecast.java
new file mode 100644
index 0000000..5dfacc9
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/forecast/DayForecast.java
@@ -0,0 +1,19 @@
+package com.flaremicro.flaretv.visualforecast.forecast;
+
+public class DayForecast {
+ public byte hiTemp;
+ public byte loTemp;
+ public byte iconId;
+ public String weatherLine1;
+ public String weatherLine2;
+ public float percipPercent;
+
+ public DayForecast(byte hiTemp, byte loTemp, byte iconId, String weatherLine1, String weatherLine2, float percipPercent){
+ this.hiTemp = hiTemp;
+ this.loTemp = loTemp;
+ this.iconId = iconId;
+ this.weatherLine1 = weatherLine1;
+ this.weatherLine2 = weatherLine2;
+ this.percipPercent = percipPercent;
+ }
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/forecast/ForecastDetails.java b/src/com/flaremicro/flaretv/visualforecast/forecast/ForecastDetails.java
new file mode 100644
index 0000000..37eefb8
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/forecast/ForecastDetails.java
@@ -0,0 +1,20 @@
+package com.flaremicro.flaretv.visualforecast.forecast;
+
+public class ForecastDetails {
+ //Perhaps could be hashmap?
+ private TownForecast[] towns;
+
+ public ForecastDetails(){
+
+ }
+
+
+ public void setTownForecast(TownForecast[] towns){
+ this.towns = towns;
+ }
+
+ public TownForecast[] getTownForecast()
+ {
+ return towns;
+ }
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/forecast/ForecastInformation.java b/src/com/flaremicro/flaretv/visualforecast/forecast/ForecastInformation.java
deleted file mode 100644
index bac895d..0000000
--- a/src/com/flaremicro/flaretv/visualforecast/forecast/ForecastInformation.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.flaremicro.flaretv.visualforecast.forecast;
-
-public class ForecastInformation {
-
-}
diff --git a/src/com/flaremicro/flaretv/visualforecast/forecast/MockForecastProvider.java b/src/com/flaremicro/flaretv/visualforecast/forecast/MockForecastProvider.java
new file mode 100644
index 0000000..dae6732
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/forecast/MockForecastProvider.java
@@ -0,0 +1,109 @@
+package com.flaremicro.flaretv.visualforecast.forecast;
+
+import java.util.Random;
+
+import com.flaremicro.flaretv.visualforecast.icons.IconProvider;
+
+public class MockForecastProvider {
+
+
+ private static final String[] townNames = {
+ "Vancouver",
+ "Burnaby",
+ "Kamloops",
+ "Kelona",
+ "Lytton"
+ };
+
+ private final static WeatherType[] possibleWeather = {
+ new WeatherType(IconProvider.BLIZZARD.id, "Blizzard", true),
+ new WeatherType(IconProvider.CLOUD.id, "Cloudy", false),
+ new WeatherType(IconProvider.CLOUDY_CLOUDY.id, "Very", "Cloudy", false),
+ new WeatherType(IconProvider.FREEZING_RAIN.id, "Freezing", "Rain", true),
+ new WeatherType(IconProvider.LIGHTNING_STORM.id, "Thunder", "Storm", true),
+ new WeatherType(IconProvider.LIGHTNING_BLIZZARD.id, "Blizzard", "T'Storm", true),
+ new WeatherType(IconProvider.PARTLY_CLOUDY.id, "Partly", "Cloudy", false),
+ new WeatherType(IconProvider.RAIN.id, "Rain", true),
+ new WeatherType(IconProvider.RAIN_HEAVIEST.id, "Extreme","Rain", true),
+ new WeatherType(IconProvider.RAIN_HEAVY.id, "Heavy","Rain", true),
+ new WeatherType(IconProvider.RAIN_LIGHT.id, "Light","Rain", true),
+ new WeatherType(IconProvider.RAIN_LIGHTEST.id, "Drizzle", true),
+ new WeatherType(IconProvider.RAIN_SNOW.id, "Rain","Snow", true),
+ new WeatherType(IconProvider.RAIN_VANCOUVER.id, "Vancouver","Rain", true),
+ new WeatherType(IconProvider.SCATTERD_SHOWERS.id, "Scattered","Showers", true),
+ new WeatherType(IconProvider.SCATTERD_THUNDERSTORMS.id, "Scattered","T'Storms", true),
+ new WeatherType(IconProvider.SNOW.id, "Snow", true),
+ new WeatherType(IconProvider.SUN.id, "Sun", false),
+ };
+
+
+ public static ForecastDetails provideMockForecast()
+ {
+ Random random = new Random();
+ ForecastDetails fd = new ForecastDetails();
+ fd.setTownForecast(provideTownForecast(random));
+ return fd;
+
+ }
+
+ private static TownForecast[] provideTownForecast(Random random) {
+ TownForecast[] tf = new TownForecast[townNames.length];
+ for(int i = 0; i < tf.length; i++)
+ {
+ tf[i] = new TownForecast(townNames[i], provideDayForecast(random));
+ }
+ return tf;
+ }
+
+ private static DayForecast[] provideDayForecast(Random random)
+ {
+ DayForecast[] df = new DayForecast[7 + random.nextInt(2)];
+ for(int i = 0; i < df.length; i++)
+ {
+ byte hiTemp = (byte)(random.nextInt(60)-20);
+ byte loTemp = (byte)(random.nextInt(60)-20);
+ if(hiTemp < loTemp)
+ {
+ byte temp = hiTemp;
+ hiTemp = loTemp;
+ loTemp = temp;
+ }
+
+ byte iconId = 0;
+ String weatherLine1 = null;
+ String weatherLine2 = null;
+ float percipPercent = ValueCheck.NO_DATA_FLOAT;
+
+ WeatherType wt = possibleWeather[random.nextInt(possibleWeather.length)];
+ iconId = wt.iconId;
+ weatherLine1 = wt.line1;
+ weatherLine2 = wt.line2;
+
+ if(wt.hasPercipitation)
+ {
+ percipPercent = random.nextFloat() * 100;
+ }
+
+ df[i] = new DayForecast(hiTemp, loTemp, iconId, weatherLine1, weatherLine2, percipPercent);
+ }
+ return df;
+ }
+
+}
+
+class WeatherType{
+ byte iconId;
+ String line1;
+ String line2;
+ boolean hasPercipitation;
+
+ public WeatherType(byte iconId, String line1, boolean hasPercipitation){
+ this(iconId, line1, null, hasPercipitation);
+ }
+ public WeatherType(byte iconId, String line1, String line2, boolean hasPercipitation){
+ this.iconId = iconId;
+ this.line1 = line1;
+ this.line2 = line2;
+ this.hasPercipitation = hasPercipitation;
+ }
+}
\ No newline at end of file
diff --git a/src/com/flaremicro/flaretv/visualforecast/forecast/TownForecast.java b/src/com/flaremicro/flaretv/visualforecast/forecast/TownForecast.java
new file mode 100644
index 0000000..693716a
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/forecast/TownForecast.java
@@ -0,0 +1,19 @@
+package com.flaremicro.flaretv.visualforecast.forecast;
+
+public class TownForecast {
+ public TownForecast(String townName, DayForecast[] dayForecast){
+ this.townName = townName;
+ this.dayForecast = dayForecast;
+ }
+
+ private final String townName;
+ private final DayForecast[] dayForecast;
+
+ public DayForecast[] getDayForecast() {
+ return dayForecast;
+ }
+
+ public String getTownName() {
+ return townName;
+ }
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/forecast/ValueCheck.java b/src/com/flaremicro/flaretv/visualforecast/forecast/ValueCheck.java
new file mode 100644
index 0000000..f718147
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/forecast/ValueCheck.java
@@ -0,0 +1,45 @@
+package com.flaremicro.flaretv.visualforecast.forecast;
+
+public class ValueCheck {
+ //Utility for no data
+ public static final byte NO_DATA_BYTE = Byte.MIN_VALUE;
+ public static final short NO_DATA_SHORT = Short.MIN_VALUE;
+ public static final int NO_DATA_INT = Integer.MIN_VALUE;
+ public static final long NO_DATA_LONG = Long.MIN_VALUE;
+ public static final float NO_DATA_FLOAT = Float.NaN;
+ public static final double NO_DATA_DOUBLE = Double.NaN;
+
+ public static final boolean valueNoData(byte f)
+ {
+ return f == NO_DATA_BYTE;
+ }
+ public static final boolean valueNoData(short f)
+ {
+ return f == NO_DATA_SHORT;
+ }
+
+ public static final boolean valueNoData(int f)
+ {
+ return f == NO_DATA_INT;
+ }
+
+ public static final boolean valueNoData(long f)
+ {
+ return f == NO_DATA_LONG;
+ }
+
+ public static final boolean valueNoData(float f)
+ {
+ return Float.isInfinite(f) || Float.isNaN(f);
+ }
+
+ public static final boolean valueNoData(double d)
+ {
+ return Double.isInfinite(d) || Double.isNaN(d);
+ }
+
+ public static final boolean valueNoData(Object o)
+ {
+ return o == null;
+ }
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/graphics/DrawingUtil.java b/src/com/flaremicro/flaretv/visualforecast/graphics/DrawingUtil.java
new file mode 100644
index 0000000..86a08a5
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/graphics/DrawingUtil.java
@@ -0,0 +1,76 @@
+package com.flaremicro.flaretv.visualforecast.graphics;
+
+import java.awt.Color;
+import java.awt.GradientPaint;
+import java.awt.Graphics2D;
+import java.awt.Polygon;
+
+public class DrawingUtil {
+ public static void drawGradientRect(Graphics2D g, int x, int y, int w, int h, int borderWidth, Color innerColor, Color outerColor) {
+
+ g.setColor(innerColor);
+ g.fillRect(x, y, w, h);
+
+ g.setPaint(new GradientPaint(x, 0, outerColor, x + borderWidth, 0, innerColor));
+ g.fillRect(x, y, borderWidth, h);
+
+ g.setPaint(new GradientPaint(x + w - borderWidth, 0, innerColor, x + w, 0, outerColor));
+ g.fillRect(x + w - borderWidth, y, borderWidth, h);
+
+ g.setPaint(new GradientPaint(0, y, outerColor, 0, y + borderWidth, innerColor));
+ g.setClip(new Polygon(new int[] { x, x + w, x + w - borderWidth, x + borderWidth }, new int[] { y, y, y + borderWidth, y + borderWidth }, 4));
+ g.fillRect(x, y, w, borderWidth);
+
+ g.setClip(new Polygon(new int[] { x, x + w, x + w - borderWidth, x + borderWidth }, new int[] { y + h, y + h, y + h - borderWidth, y + h - borderWidth }, 4));
+ g.setPaint(new GradientPaint(0, y + h - borderWidth, innerColor, 0, y + h, outerColor));
+ g.fillRect(x, y + h - borderWidth, w, borderWidth);
+
+ g.setClip(null);
+
+ }
+
+ public static void drawOutlinedString(Graphics2D g2d, int x, int y, String text, Color textColor, Color outline, int outlineSize) {
+ g2d.setColor(outline);
+ for (int i = 1; i <= outlineSize; i++)
+ {
+ g2d.drawString(text, x + i, y);
+ g2d.drawString(text, x - i, y);
+ g2d.drawString(text, x, y + i);
+ g2d.drawString(text, x, y - i);
+ g2d.drawString(text, x + i, y + i);
+ g2d.drawString(text, x - i, y - i);
+ g2d.drawString(text, x - i, y + i);
+ g2d.drawString(text, x + i, y - i);
+ }
+
+ g2d.setColor(textColor);
+ g2d.drawString(text, x, y);
+ /*
+ * AffineTransform transform = g2d.getTransform();
+ * transform.translate(x, y); g2d.transform(transform);
+ * g2d.setColor(outline); FontRenderContext frc =
+ * g2d.getFontRenderContext(); TextLayout tl = new TextLayout(text,
+ * g2d.getFont(), frc); Shape shape = tl.getOutline(null);
+ * g2d.setStroke(new BasicStroke(outlineSize)); g2d.draw(shape);
+ * g2d.setColor(textColor); g2d.fill(shape);
+ */
+ }
+
+ public static void drawOutlinedString(Graphics2D g2d, int x, int y, String text, Color textColor, Color outline, int outlineSize, float outlineStep) {
+ g2d.setColor(outline);
+ for (int i = 1; i <= outlineSize; i++)
+ {
+ g2d.drawString(text, x + i*outlineStep, y);
+ g2d.drawString(text, x - i*outlineStep, y);
+ g2d.drawString(text, x, y + i*outlineStep);
+ g2d.drawString(text, x, y - i*outlineStep);
+ g2d.drawString(text, x + i*outlineStep, y + i*outlineStep);
+ g2d.drawString(text, x - i*outlineStep, y - i*outlineStep);
+ g2d.drawString(text, x - i*outlineStep, y + i*outlineStep);
+ g2d.drawString(text, x + i*outlineStep, y - i*outlineStep);
+ }
+
+ g2d.setColor(textColor);
+ g2d.drawString(text, x, y);
+ }
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/graphics/FontManager.java b/src/com/flaremicro/flaretv/visualforecast/graphics/FontManager.java
new file mode 100644
index 0000000..59ad676
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/graphics/FontManager.java
@@ -0,0 +1,107 @@
+package com.flaremicro.flaretv.visualforecast.graphics;
+
+import java.awt.Font;
+import java.awt.FontFormatException;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class FontManager {
+ private final Font baseFont;
+ private static FontManager instance = null;
+
+ private Map urlToFontMapping = new HashMap();
+ private List fonts = new ArrayList();
+
+ private FontManager() {
+ BufferedImage bufferedImage = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY);
+ Graphics g = bufferedImage.createGraphics();
+ baseFont = g.getFont();
+ g.dispose();
+ }
+
+ public static FontManager getInstance() {
+ if (instance == null)
+ {
+ instance = new FontManager();
+ }
+ return instance;
+ }
+
+ public Font getFont(int fontId){
+ if(fontId < 0 || fontId >= fonts.size())
+ return baseFont;
+ else return fonts.get(fontId);
+ }
+
+ public Font getFont(URL fontResource){
+ Integer i = urlToFontMapping.get(fontResource);
+ if(i == null)
+ return baseFont;
+ else return fonts.get(i);
+ }
+
+ public int getFontID(URL fontResource){
+ Integer i = urlToFontMapping.get(fontResource);
+ if(i == null)
+ return -1;
+ else return i;
+ }
+
+ public Font getOrCreateFont(int fontFormat, URL fontResource)
+ {
+ if(fontResource == null)
+ return baseFont.deriveFont(Font.PLAIN);
+ int i = getOrPrepareFont(fontFormat, fontResource);
+ return fonts.get(i);
+ }
+
+ public int getOrPrepareFont(int fontFormat, URL fontResource)
+ {
+ Integer i = urlToFontMapping.get(fontResource);
+ if(i == null)
+ {
+ Font f = baseFont.deriveFont(Font.PLAIN);
+ if(fontResource == null)
+ return -1;
+ InputStream stream = null;
+ try
+ {
+ stream = fontResource.openStream();
+ f = Font.createFont(fontFormat, stream);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ catch (FontFormatException e)
+ {
+ e.printStackTrace();
+ }
+ finally{
+ if(stream != null)
+ try
+ {
+ stream.close();
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+ synchronized(fonts)
+ {
+ i = fonts.size();
+ fonts.add(f);
+ urlToFontMapping.put(fontResource, i);
+ }
+ }
+ return i;
+ }
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/graphics/RenderConstants.java b/src/com/flaremicro/flaretv/visualforecast/graphics/RenderConstants.java
new file mode 100644
index 0000000..20be0be
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/graphics/RenderConstants.java
@@ -0,0 +1,36 @@
+package com.flaremicro.flaretv.visualforecast.graphics;
+
+import java.awt.Color;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+
+public class RenderConstants {
+ public static final int W = 640, H = 480;
+ public static final int INFOBAR_HEIGHT = 80;
+ public static final int TOPBAR_HEIGHT = 80;
+ public static final int MAINBAR_HEIGHT = H - INFOBAR_HEIGHT - TOPBAR_HEIGHT;
+
+ public static final int HEADERBAR_Y = 20;
+ public static final double HEADERBAR_SHEAR = 0.2;
+ public static final int HEADERBAR_OFFSET = 20;
+ public static final int HEADERBAR_WIDTH = 400 + HEADERBAR_OFFSET;
+ public static final int HEADERBAR_HEIGHT = TOPBAR_HEIGHT - HEADERBAR_Y;
+
+ public static final int TIMEBAR_Y = 40;
+ public static final int TIMEBAR_OFFSET = 20;
+ public static final int TIMEBAR_WIDTH = 230 + HEADERBAR_OFFSET;
+ public static final int TIMEBAR_HEIGHT = TOPBAR_HEIGHT - TIMEBAR_Y;
+
+ public static final int STROKE_WIDTH = 2;
+ public static final int STROKE_OFFSET = STROKE_WIDTH / 2;
+
+ public static final int SIDE_OFFSET = 60;
+
+ public static final DateFormat DATE_FORMAT = new SimpleDateFormat("MMMM d");
+ public static final DateFormat TIME_FORMAT = new SimpleDateFormat("hh:mm:ss a");
+
+
+ public static final Color BG_PURPLE = new Color(0x2b29b3);
+ public static final Color BG_OORANGE = new Color(0xff8c00);
+ public static final Color BG_BLUE = new Color(0x394aa8);
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/Icon.java b/src/com/flaremicro/flaretv/visualforecast/icons/Icon.java
index 4259d06..71d54f3 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/Icon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/Icon.java
@@ -2,7 +2,13 @@ package com.flaremicro.flaretv.visualforecast.icons;
import java.awt.Graphics2D;
-public interface Icon {
- public boolean isAnimated();
- public void drawIcon(Graphics2D g2d, float scale, int animationStep);
+public abstract class Icon {
+
+ public Icon(int i){
+ this.id = (byte)i;
+ }
+
+ public final byte id;
+ public abstract boolean isAnimated();
+ public abstract void drawIcon(Graphics2D g2d, float scale, int animationStep);
}
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/IconProvider.java b/src/com/flaremicro/flaretv/visualforecast/icons/IconProvider.java
index 80665f4..9f0dd7d 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/IconProvider.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/IconProvider.java
@@ -5,6 +5,7 @@ import java.awt.geom.AffineTransform;
import com.flaremicro.flaretv.visualforecast.icons.impl.BlizzardIcon;
import com.flaremicro.flaretv.visualforecast.icons.impl.CloudIcon;
+import com.flaremicro.flaretv.visualforecast.icons.impl.InvalidIcon;
import com.flaremicro.flaretv.visualforecast.icons.impl.LightningIcon;
import com.flaremicro.flaretv.visualforecast.icons.impl.LightningOverlay;
import com.flaremicro.flaretv.visualforecast.icons.impl.LightningStormIcon;
@@ -18,28 +19,44 @@ import com.flaremicro.flaretv.visualforecast.icons.impl.SunIcon;
public class IconProvider {
+ public static final Icon[] INDEXED_ICONS = new Icon[64];
- public static final Icon SUN = new SunIcon();
- public static final Icon CLOUD = new CloudIcon();
- public static final Icon PARTLY_CLOUDY = new PartlyCloudyIcon(CLOUD, SUN);
- public static final Icon CLOUDY_CLOUDY = new PartlyCloudyIcon(CLOUD, CLOUD);
- public static final Icon RAIN_LIGHTEST = new RainIcon(2, 2F, CLOUD);
- public static final Icon RAIN_LIGHT = new RainIcon(3, 2F, CLOUD);
- public static final Icon RAIN = new RainIcon(3, 1F, CLOUD);
- public static final Icon RAIN_HEAVY = new RainIcon(4, 1F, CLOUD);
- public static final Icon RAIN_HEAVIEST = new RainIcon(5, 1F, CLOUD);
- public static final Icon RAIN_VANCOUVER = new RainIcon(6, 1F, CLOUD);
- public static final Icon SCATTERD_SHOWERS = new PartlyCloudyIcon(new RainIcon(2, 4F, CLOUD), SUN);
- public static final Icon SNOWFLAKE = new SnowflakeIcon();
- public static final Icon SNOW = new SnowIcon(CLOUD, SNOWFLAKE);
- public static final Icon BLIZZARD = new BlizzardIcon(CLOUD, SNOWFLAKE);
- public static final Icon RAIN_SNOW = new RainSnowIcon(RAIN_LIGHTEST, SNOWFLAKE, true);
- public static final Icon FREEZING_RAIN = new RainSnowIcon(RAIN_LIGHT, SNOWFLAKE, false);
- public static final Icon LIGHTNING_BOLT = new LightningIcon();
- public static final Icon LIGHTNING_STORM = new LightningStormIcon(CLOUD, LIGHTNING_BOLT);
- public static final Icon SMALL_CLOUD = new SmallCloudIcon();
- public static final Icon LIGHTNING_OVERLAY = new LightningOverlay(SMALL_CLOUD, LIGHTNING_BOLT, BLIZZARD);
+ public static final Icon INVALID = registerIcon(setMainIcon(new InvalidIcon(0)));
+ public static final Icon SUN = registerIcon(new SunIcon(1));
+ public static final Icon CLOUD = registerIcon(new CloudIcon(2));
+ public static final Icon PARTLY_CLOUDY = registerIcon(new PartlyCloudyIcon(3, CLOUD, SUN));
+ public static final Icon CLOUDY_CLOUDY = registerIcon(new PartlyCloudyIcon(4, CLOUD, CLOUD));
+ public static final Icon RAIN_LIGHTEST = registerIcon(new RainIcon(5, 2, 2F, CLOUD));
+ public static final Icon RAIN_LIGHT = registerIcon(new RainIcon(6, 3, 2F, CLOUD));
+ public static final Icon RAIN = registerIcon(new RainIcon(7, 3, 1F, CLOUD));
+ public static final Icon RAIN_HEAVY = registerIcon(new RainIcon(8, 4, 1F, CLOUD));
+ public static final Icon RAIN_HEAVIEST = registerIcon(new RainIcon(9, 5, 1F, CLOUD));
+ public static final Icon RAIN_VANCOUVER = registerIcon(new RainIcon(10, 6, 1F, CLOUD));
+ public static final Icon SCATTERD_SHOWERS = registerIcon(new PartlyCloudyIcon(11, new RainIcon(-1, 2, 4F, CLOUD), SUN));
+ public static final Icon SNOWFLAKE = registerIcon(new SnowflakeIcon(12));
+ public static final Icon SNOW = registerIcon(new SnowIcon(13, CLOUD, SNOWFLAKE));
+ public static final Icon BLIZZARD = registerIcon(new BlizzardIcon(14, CLOUD, SNOWFLAKE));
+ public static final Icon RAIN_SNOW = registerIcon(new RainSnowIcon(15, RAIN_LIGHTEST, SNOWFLAKE, true));
+ public static final Icon FREEZING_RAIN = registerIcon(new RainSnowIcon(16, RAIN_LIGHT, SNOWFLAKE, false));
+ public static final Icon LIGHTNING_BOLT = registerIcon(new LightningIcon(17));
+ public static final Icon LIGHTNING_STORM = registerIcon(new LightningStormIcon(18, CLOUD, LIGHTNING_BOLT));
+ public static final Icon SMALL_CLOUD = registerIcon(new SmallCloudIcon(19));
+ public static final Icon LIGHTNING_BLIZZARD = registerIcon(new LightningOverlay(20, SMALL_CLOUD, LIGHTNING_BOLT, BLIZZARD));
+ public static final Icon SCATTERD_THUNDERSTORMS = registerIcon(new PartlyCloudyIcon(21, LIGHTNING_STORM, SUN));
+ private static Icon registerIcon(Icon icon)
+ {
+ INDEXED_ICONS[icon.id] = icon;
+ return icon;
+ }
+
+ private static Icon setMainIcon(Icon icon) {
+ for(int i = 0; i < INDEXED_ICONS.length; i++){
+ INDEXED_ICONS[i] = icon;
+ }
+ return icon;
+ }
+
public static void drawIcon(Graphics2D g2d, Icon icon, int x, int y, int scale, int animationStep)
{
if(icon != null)
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/BlizzardIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/BlizzardIcon.java
index 8851f81..d9205ed 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/BlizzardIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/BlizzardIcon.java
@@ -5,14 +5,15 @@ import java.awt.geom.AffineTransform;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class BlizzardIcon implements Icon {
+public class BlizzardIcon extends Icon {
private final Icon cloudIcon;
private final Icon snowflakeIcon;
- public BlizzardIcon(Icon cloudIcon, Icon snowflakeIcon)
+ public BlizzardIcon(int id, Icon cloudIcon, Icon snowflakeIcon)
{
+ super(id);
this.cloudIcon = cloudIcon;
this.snowflakeIcon = snowflakeIcon;
}
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/CloudIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/CloudIcon.java
index 67e6447..658cdfa 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/CloudIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/CloudIcon.java
@@ -7,8 +7,8 @@ import java.awt.geom.Ellipse2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class CloudIcon implements Icon {
- Ellipse2D.Float[] cloudCircles = new Ellipse2D.Float[]{
+public class CloudIcon extends Icon {
+ private final Ellipse2D.Float[] cloudCircles = new Ellipse2D.Float[]{
new Ellipse2D.Float(0, 0.5F, 0.28F, 0.325F),
new Ellipse2D.Float(0.142F, 0.619F, 0.287F, 0.231F),
new Ellipse2D.Float(0.666F, 0.597F, 0.208F, 0.234F),
@@ -20,21 +20,21 @@ public class CloudIcon implements Icon {
};
- Ellipse2D.Float[] extraStroke = new Ellipse2D.Float[]{
+ private final Ellipse2D.Float[] extraStroke = new Ellipse2D.Float[]{
new Ellipse2D.Float(0.142F, 0.619F, 0.287F, 0.231F),
new Ellipse2D.Float(0.666F, 0.597F, 0.208F, 0.234F)
};
- Ellipse2D.Float[] overStroke = new Ellipse2D.Float[]{
+ private final Ellipse2D.Float[] overStroke = new Ellipse2D.Float[]{
new Ellipse2D.Float(0.233F, 0.150F, 0.369F, 0.677F),
new Ellipse2D.Float(0.113F, 0.326F, 0.266F, 0.356F),
new Ellipse2D.Float(0.749F, 0.412F, 0.251F, 0.417F),
new Ellipse2D.Float(0.652F, 0.555F, 0.150F, 0.136F),
};
- Ellipse2D.Float[] lightCircles = new Ellipse2D.Float[]{
+ private final Ellipse2D.Float[] lightCircles = new Ellipse2D.Float[]{
new Ellipse2D.Float(0.309F, 0.173F, 0.209F, 0.235F),
new Ellipse2D.Float(0.554F, 0.276F, 0.204F, 0.314F),
new Ellipse2D.Float(0.770F, 0.440F, 0.204F, 0.235F),
@@ -42,7 +42,7 @@ public class CloudIcon implements Icon {
new Ellipse2D.Float(0.259F, 0.460F, 0.314F, 0.235F),
};
- Ellipse2D.Float[] overLight = new Ellipse2D.Float[]{
+ private final Ellipse2D.Float[] overLight = new Ellipse2D.Float[]{
new Ellipse2D.Float(0.328F, 0.188F, 0.209F, 0.235F),
new Ellipse2D.Float(0.573F, 0.296F, 0.204F, 0.314F),
new Ellipse2D.Float(0.789F, 0.456F, 0.204F, 0.235F),
@@ -50,6 +50,10 @@ public class CloudIcon implements Icon {
new Ellipse2D.Float(0.288F, 0.476F, 0.314F, 0.235F),
};
+ public CloudIcon(int id)
+ {
+ super(id);
+ }
@Override
public void drawIcon(Graphics2D g2d, float scale, int animationStep) {
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/InvalidIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/InvalidIcon.java
new file mode 100644
index 0000000..ec502e7
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/InvalidIcon.java
@@ -0,0 +1,35 @@
+package com.flaremicro.flaretv.visualforecast.icons.impl;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Graphics2D;
+import com.flaremicro.flaretv.visualforecast.graphics.DrawingUtil;
+import com.flaremicro.flaretv.visualforecast.graphics.FontManager;
+import com.flaremicro.flaretv.visualforecast.icons.Icon;
+
+public class InvalidIcon extends Icon {
+
+ private Font fnt = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf"));
+
+ public InvalidIcon(int i)
+ {
+ super(i);
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, float scale, int animationStep) {
+ g2d.setFont(fnt.deriveFont(0.8F));
+ g2d.translate(0.2F, 0.8F);
+ DrawingUtil.drawOutlinedString(g2d, 0, 0, "X", Color.YELLOW, Color.BLACK, 1, 2/scale);
+ g2d.translate(0.2F, 0F);
+ DrawingUtil.drawOutlinedString(g2d, 0, 0, "?", Color.RED, Color.BLACK, 1, 2/scale);
+ g2d.translate(-0.4F, -0.8F);
+ }
+
+
+ @Override
+ public boolean isAnimated() {
+ return false;
+ }
+
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningCloudIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningCloudIcon.java
new file mode 100644
index 0000000..5d1834b
--- /dev/null
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningCloudIcon.java
@@ -0,0 +1,36 @@
+package com.flaremicro.flaretv.visualforecast.icons.impl;
+
+import java.awt.Graphics2D;
+import com.flaremicro.flaretv.visualforecast.icons.Icon;
+
+public class LightningCloudIcon extends Icon {
+
+ private final Icon boltIcon;
+ private final Icon smallCloudIcon;
+
+ public LightningCloudIcon(int id, Icon smallCloudIcon, Icon boltIcon) {
+ super(id);
+ this.smallCloudIcon = smallCloudIcon;
+ this.boltIcon = boltIcon;
+ }
+
+ @Override
+ public void drawIcon(Graphics2D g2d, float scale, int animationStep) {
+ g2d.scale(0.8F, 0.5F);
+ g2d.translate(0.0F, 0.8F);
+ boltIcon.drawIcon(g2d, scale/1.5F, animationStep);
+ g2d.translate(-0.0F, -0.8F);
+ g2d.scale(1.25F, 2);
+
+ g2d.scale(0.6F, 0.4F);
+ g2d.translate(0.3F, 0.5F);
+ smallCloudIcon.drawIcon(g2d, scale/2, animationStep);
+ g2d.translate(-0.3F, -0.5F);
+ g2d.scale(1.66666666667F, 2.5F);
+ }
+
+ @Override
+ public boolean isAnimated() {
+ return boltIcon.isAnimated() || smallCloudIcon.isAnimated();
+ }
+}
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningIcon.java
index 7127e53..aaec729 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningIcon.java
@@ -7,7 +7,7 @@ import java.awt.geom.Path2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class LightningIcon implements Icon {
+public class LightningIcon extends Icon {
Path2D.Float boltPath = new Path2D.Float();
Path2D.Float shinePath = new Path2D.Float();
@@ -39,8 +39,9 @@ public class LightningIcon implements Icon {
new Color(0xFFFF00),
};
- public LightningIcon()
+ public LightningIcon(int id)
{
+ super(id);
boltPath.moveTo(0.380, 0);
boltPath.lineTo(0.680, 0);
boltPath.lineTo(0.577, 0.206);
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningOverlay.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningOverlay.java
index 782addf..03766c2 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningOverlay.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningOverlay.java
@@ -3,13 +3,14 @@ package com.flaremicro.flaretv.visualforecast.icons.impl;
import java.awt.Graphics2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class LightningOverlay implements Icon {
+public class LightningOverlay extends Icon {
private final Icon boltIcon;
private final Icon smallCloudIcon;
private final Icon weatherIcon;
- public LightningOverlay(Icon smallCloudIcon, Icon boltIcon, Icon weatherIcon) {
+ public LightningOverlay(int id, Icon smallCloudIcon, Icon boltIcon, Icon weatherIcon) {
+ super(id);
this.smallCloudIcon = smallCloudIcon;
this.boltIcon = boltIcon;
this.weatherIcon = weatherIcon;
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningStormIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningStormIcon.java
index ad7ed78..6f3a8ae 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningStormIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/LightningStormIcon.java
@@ -4,13 +4,14 @@ import java.awt.BasicStroke;
import java.awt.Graphics2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class LightningStormIcon implements Icon {
+public class LightningStormIcon extends Icon {
private final Icon boltIcon;
private final Icon cloudIcon;
- public LightningStormIcon(Icon cloudIcon, Icon boltIcon)
+ public LightningStormIcon(int id, Icon cloudIcon, Icon boltIcon)
{
+ super(id);
this.cloudIcon = cloudIcon;
this.boltIcon = boltIcon;
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/PartlyCloudyIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/PartlyCloudyIcon.java
index 1ee7382..d0c5e9c 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/PartlyCloudyIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/PartlyCloudyIcon.java
@@ -4,12 +4,13 @@ import java.awt.Graphics2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class PartlyCloudyIcon implements Icon {
+public class PartlyCloudyIcon extends Icon {
private Icon cloud;
private Icon sun;
- public PartlyCloudyIcon(Icon cloud, Icon sun)
+ public PartlyCloudyIcon(int id, Icon cloud, Icon sun)
{
+ super(id);
this.cloud = cloud;
this.sun = sun;
}
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/RainIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/RainIcon.java
index cf62ee7..ec8b7c5 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/RainIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/RainIcon.java
@@ -7,7 +7,7 @@ import java.awt.geom.Path2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class RainIcon implements Icon {
+public class RainIcon extends Icon {
private final int rainCount;
private final float rainSpace;
private final Icon cloudIcon;
@@ -28,8 +28,9 @@ public class RainIcon implements Icon {
new Color(0x0066FF),
};
- public RainIcon(int rainCount, float rainSpace, Icon cloudIcon)
+ public RainIcon(int id, int rainCount, float rainSpace, Icon cloudIcon)
{
+ super(id);
this.rainCount = rainCount;
this.rainSpace = rainSpace * 0.125F;
this.cloudIcon = cloudIcon;
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/RainSnowIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/RainSnowIcon.java
index a964408..5e7a1bd 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/RainSnowIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/RainSnowIcon.java
@@ -3,15 +3,16 @@ package com.flaremicro.flaretv.visualforecast.icons.impl;
import java.awt.Graphics2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class RainSnowIcon implements Icon {
+public class RainSnowIcon extends Icon {
private final Icon rainIcon;
private final Icon snowflakeIcon;
private final boolean snow;
- public RainSnowIcon(Icon rainIcon, Icon snowflakeIcon, boolean snow)
+ public RainSnowIcon(int id, Icon rainIcon, Icon snowflakeIcon, boolean snow)
{
+ super(id);
this.rainIcon = rainIcon;
this.snowflakeIcon = snowflakeIcon;
this.snow = snow;
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/SmallCloudIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/SmallCloudIcon.java
index f8fc5db..39a5dff 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/SmallCloudIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/SmallCloudIcon.java
@@ -6,8 +6,13 @@ import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class SmallCloudIcon implements Icon {
- Ellipse2D.Float[] cloudCircles = new Ellipse2D.Float[]{
+public class SmallCloudIcon extends Icon {
+ public SmallCloudIcon(int id) {
+ super(id);
+ }
+
+
+ private final Ellipse2D.Float[] cloudCircles = new Ellipse2D.Float[]{
new Ellipse2D.Float(0.456F, 0.241F, 0.346F, 0.748F),
new Ellipse2D.Float(0.655F, 0.238F, 0.356F, 0.748F),
new Ellipse2D.Float(0.480F, 0.043F, 0.341F, 0.523F),
@@ -16,14 +21,14 @@ public class SmallCloudIcon implements Icon {
new Ellipse2D.Float(0.000F, 0.199F, 0.428F, 0.801F)
};
- Ellipse2D.Float[] lightCircles = new Ellipse2D.Float[]{
+ private final Ellipse2D.Float[] lightCircles = new Ellipse2D.Float[]{
new Ellipse2D.Float(0.196F, 0.052F, 0.439F, 0.748F),
new Ellipse2D.Float(0.030F, 0.230F, 0.439F, 0.654F),
new Ellipse2D.Float(0.709F, 0.300F, 0.218F, 0.335F),
new Ellipse2D.Float(0.429F, 0.498F, 0.218F, 0.335F)
};
- Ellipse2D.Float[] overLight = new Ellipse2D.Float[]{
+ private final Ellipse2D.Float[] overLight = new Ellipse2D.Float[]{
new Ellipse2D.Float(0.183F, 0.124F, 0.478F, 0.713F),
new Ellipse2D.Float(0.040F, 0.264F, 0.478F, 0.713F),
new Ellipse2D.Float(0.716F, 0.335F, 0.237F, 0.365F),
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/SnowIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/SnowIcon.java
index b64c6c6..58d1c26 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/SnowIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/SnowIcon.java
@@ -5,14 +5,15 @@ import java.awt.geom.AffineTransform;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class SnowIcon implements Icon {
+public class SnowIcon extends Icon {
private final Icon cloudIcon;
private final Icon snowflakeIcon;
- public SnowIcon(Icon cloudIcon, Icon snowflakeIcon)
+ public SnowIcon(int id, Icon cloudIcon, Icon snowflakeIcon)
{
+ super(id);
this.cloudIcon = cloudIcon;
this.snowflakeIcon = snowflakeIcon;
}
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/SnowflakeIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/SnowflakeIcon.java
index c7cba30..6a971ec 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/SnowflakeIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/SnowflakeIcon.java
@@ -7,7 +7,7 @@ import java.awt.geom.Path2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class SnowflakeIcon implements Icon {
+public class SnowflakeIcon extends Icon {
Path2D.Float flakePath = new Path2D.Float();
Path2D.Float gradPath = new Path2D.Float();
Path2D.Float trianglePath = new Path2D.Float();
@@ -27,8 +27,9 @@ public class SnowflakeIcon implements Icon {
new Color(0x2288FF),
};
- public SnowflakeIcon()
+ public SnowflakeIcon(int id)
{
+ super(id);
flakePath.moveTo(0.400, 0);
flakePath.lineTo(0.600, 0);
flakePath.lineTo(0.600, 0.327);
diff --git a/src/com/flaremicro/flaretv/visualforecast/icons/impl/SunIcon.java b/src/com/flaremicro/flaretv/visualforecast/icons/impl/SunIcon.java
index b65f077..307ea46 100644
--- a/src/com/flaremicro/flaretv/visualforecast/icons/impl/SunIcon.java
+++ b/src/com/flaremicro/flaretv/visualforecast/icons/impl/SunIcon.java
@@ -8,7 +8,7 @@ import java.awt.geom.Path2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon;
-public class SunIcon implements Icon {
+public class SunIcon extends Icon {
Path2D.Float sunPath = new Path2D.Float();
Ellipse2D.Float sunCircle1 = new Ellipse2D.Float(0.2F, 0.2F, 0.6F, 0.6F);
Ellipse2D.Float sunInternalCircle1 = new Ellipse2D.Float(0.28F, 0.22F, 0.5F, 0.5F);
@@ -27,8 +27,9 @@ public class SunIcon implements Icon {
new Color(255, 140, 0),
new Color(255, 120, 0),
};
- public SunIcon()
+ public SunIcon(int id)
{
+ super(id);
sunPath.moveTo(0.5F, 0.0F);
sunPath.lineTo(0.605F, 0.106F);
sunPath.lineTo(0.750F, 0.067F);