Optimizations, flavours, mock weather

This commit is contained in:
Flare Microsystems
2024-03-05 01:46:07 -08:00
parent 5e21c7725a
commit 0fb5900a78
33 changed files with 978 additions and 267 deletions

View File

@@ -2,6 +2,6 @@
<classpath> <classpath>
<classpathentry kind="src" path="src"/> <classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="resources"/> <classpathentry kind="src" path="resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

View File

@@ -1,11 +1,11 @@
eclipse.preferences.version=1 eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 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.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.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=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

View File

@@ -3,24 +3,29 @@ package com.flaremicro.flaretv.visualforecast;
import java.awt.BasicStroke; import java.awt.BasicStroke;
import java.awt.Color; import java.awt.Color;
import java.awt.Font; import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.GradientPaint; import java.awt.GradientPaint;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration; 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.awt.image.VolatileImage;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar; import java.util.Calendar;
import java.util.concurrent.locks.LockSupport;
import javax.swing.JPanel; 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; 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; 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() { public RenderPanel() {
try this.addComponentListener(this);
{ font = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf"));
font = Font.createFont(Font.TRUETYPE_FONT, this.getClass().getResourceAsStream("/Star4000.ttf")); currentFlavour.initFlavour(this, MockForecastProvider.provideMockForecast(), ticks, iconAnimationTicks);
} new Thread(new TickThread(this, 30)).start();
catch (FontFormatException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
testString = "".split("\n");
new Thread(this).start();
} }
private static final int W = 640, H = 480; private Graphics2D prepareFrameBuffer() {
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() {
GraphicsConfiguration gc = this.getGraphicsConfiguration(); 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); frameBuffer = gc.createCompatibleVolatileImage(W, H);
} }
return (Graphics2D) frameBuffer.getGraphics(); return (Graphics2D) frameBuffer.getGraphics();
@@ -115,29 +85,41 @@ public class RenderPanel extends JPanel implements Runnable {
public void paintComponent(Graphics g) { public void paintComponent(Graphics g) {
super.paintComponent(g); super.paintComponent(g);
Graphics2D g2d = prepareFrameBuffer(); 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.setFont(font.deriveFont(24F));
g2d.setStroke(new BasicStroke(2)); g2d.setStroke(new BasicStroke(2));
g2d.setColor(this.backgroundPurple); g2d.setColor(BG_PURPLE);
g2d.fillRect(0, 0, W, TOPBAR_HEIGHT); 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.shear(HEADERBAR_SHEAR, 0);
g2d.fillRect(-HEADERBAR_OFFSET, HEADERBAR_Y, HEADERBAR_WIDTH, HEADERBAR_HEIGHT); 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.fillRect(W - TIMEBAR_WIDTH + TIMEBAR_OFFSET, TIMEBAR_Y, TIMEBAR_WIDTH, TIMEBAR_HEIGHT);
g2d.shear(-HEADERBAR_SHEAR, 0); 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.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.fillRect(0, H - INFOBAR_HEIGHT, W, INFOBAR_HEIGHT);
g2d.setColor(Color.DARK_GRAY); g2d.setColor(Color.DARK_GRAY);
@@ -146,120 +128,104 @@ public class RenderPanel extends JPanel implements Runnable {
g2d.setColor(Color.WHITE); g2d.setColor(Color.WHITE);
g2d.drawLine(0, H - INFOBAR_HEIGHT + STROKE_WIDTH + STROKE_OFFSET, W, H - INFOBAR_HEIGHT + STROKE_WIDTH + STROKE_OFFSET); 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.setColor(Color.GRAY);
// g2d.drawRect(60, TOPBAR_HEIGHT+2, W-120, MAINBAR_HEIGHT-4); // g2d.drawRect(60, TOPBAR_HEIGHT+2, W-120, MAINBAR_HEIGHT-4);
String dateString = DATE_FORMAT.format(System.currentTimeMillis()) + getDayOfMonthSuffix(); String dateString = DATE_FORMAT.format(System.currentTimeMillis()) + getDayOfMonthSuffix();
String timeString = TIME_FORMAT.format(System.currentTimeMillis()); String timeString = TIME_FORMAT.format(System.currentTimeMillis());
// g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, DrawingUtil.drawOutlinedString(g2d, 60, HEADERBAR_Y + 18, currentForecast, Color.WHITE, Color.BLACK, 2);
// RenderingHints.VALUE_ANTIALIAS_ON);
drawOutlinedString(g2d, 60, HEADERBAR_Y + 18, "7 Day Forecast", Color.WHITE, Color.BLACK, 1);
int sw = g2d.getFontMetrics().stringWidth(dateString); 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); 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)); 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"); g2d.setFont(font.deriveFont(26F));
drawOutlinedString(g2d, (W >> 1) - (w2 >> 1), TOPBAR_HEIGHT + 48, "EXTREME WEATHER ADVISORY", Color.RED, Color.BLACK, 2); DrawingUtil.drawOutlinedString(g2d, -20, H - INFOBAR_HEIGHT + 30, "Welcome to WeatherBC! Stay tuned for your long range forcast", Color.WHITE, Color.BLACK, 2);
g2d.setFont(font.deriveFont(30F)); }
for (int i = 0; i < testString.length; i++)
public void tick() {
this.ticks++;
if (ticks / 3.75F > this.iconAnimationTicks)
{ {
drawOutlinedString(g2d, 90, TOPBAR_HEIGHT + 78 + 25 * i, testString[i], Color.WHITE, Color.BLACK, 1); this.iconAnimationTicks++;
} //Clock and icon animations, should use repaint regions later
if (getWidth() > 0 && getHeight() > 0)
// 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);
}
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++)
{ {
g2d.drawString(text, x + i, y); repaint(this.redrawBound);
g2d.drawString(text, x - i, y); }
g2d.drawString(text, x, y + i); }
g2d.drawString(text, x, y - i); if (this.currentFlavour != null)
g2d.drawString(text, x + i, y + i); this.currentFlavour.tick(this, ticks, iconAnimationTicks);
g2d.drawString(text, x - i, y - i);
g2d.drawString(text, x - i, y + i);
g2d.drawString(text, x + i, y - i);
} }
g2d.setColor(textColor); public BufferedImage getSnapshot() {
g2d.drawString(text, x, y); return frameBuffer.getSnapshot();
/* }
* AffineTransform transform = g2d.getTransform();
* transform.translate(x, y); g2d.transform(transform); public void addRedrawBound(int x, int y, int w, int h) {
* g2d.setColor(outline); FontRenderContext frc = float wScale = getWidth() / (float) W;
* g2d.getFontRenderContext(); TextLayout tl = new TextLayout(text, float hScale = getHeight() / (float) H;
* g2d.getFont(), frc); Shape shape = tl.getOutline(null); Rectangle rect = new Rectangle((int) (x * wScale), (int) (y * hScale), (int) (w * wScale), (int) (h * hScale));
* g2d.setStroke(new BasicStroke(outlineSize)); g2d.draw(shape); if (redrawBound == null)
* g2d.setColor(textColor); g2d.fill(shape); this.redrawBound = new Rectangle((int) (x * wScale), (int) (y * hScale), (int) (w * wScale), (int) (h * hScale));
*/ else this.redrawBound.add(rect);
} }
@Override @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() { public void run() {
while (true) while (true)
{ {
this.animationTick++; this.iconAnimationTicks++;
repaint(); repaint();
LockSupport.parkNanos(125000000); LockSupport.parkNanos(125000000);
} }
} }*/
} }

View File

@@ -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);
}
}

View File

@@ -1,5 +1,7 @@
package com.flaremicro.flaretv.visualforecast; package com.flaremicro.flaretv.visualforecast;
import java.util.concurrent.locks.LockSupport;
import com.flaremicro.flaretv.visualforecast.interfaces.Tickable; import com.flaremicro.flaretv.visualforecast.interfaces.Tickable;
public class TickThread implements Runnable { public class TickThread implements Runnable {
@@ -7,20 +9,24 @@ public class TickThread implements Runnable {
private boolean running = true; private boolean running = true;
private final long sleepNanos; private final long sleepNanos;
private long nextTick = 0; //private long nextTick = 0;
TickThread(Tickable tickable, long sleepNanos) { TickThread(Tickable tickable, long sleepNanos) {
this.tickable = tickable; this.tickable = tickable;
this.sleepNanos = sleepNanos; this.sleepNanos = sleepNanos;
} }
TickThread(Tickable tickable, int ticksPerSecond) {
this(tickable, (long) ((1/(double)ticksPerSecond) * 1000000000L));
}
public void end() { public void end() {
this.running = false; this.running = false;
} }
public void run() { public void run() {
while (running) { while (running) {
while(System.nanoTime() < nextTick) /*while(System.nanoTime() < nextTick)
{ {
try try
{ {
@@ -32,12 +38,13 @@ public class TickThread implements Runnable {
} }
} }
nextTick = System.nanoTime() + sleepNanos; nextTick = System.nanoTime() + sleepNanos;
tickable.tick();*/
long nanosLost = System.nanoTime();
tickable.tick(); tickable.tick();
/*long nanosLost = System.nanoTime();
panel.tick();
nanosLost -= System.nanoTime(); nanosLost -= System.nanoTime();
if(sleepNanos+nanosLost > 0) //Unnecessary conditional?
LockSupport.parkNanos(sleepNanos+nanosLost);*/ //if(sleepNanos+nanosLost > 0)
LockSupport.parkNanos(sleepNanos+nanosLost);
} }
} }
} }

View File

@@ -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);
}
}

View File

@@ -1,5 +1,15 @@
package com.flaremicro.flaretv.visualforecast.flavour; package com.flaremicro.flaretv.visualforecast.flavour;
public interface 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);
} }

View File

@@ -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
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -1,5 +0,0 @@
package com.flaremicro.flaretv.visualforecast.forecast;
public class ForecastInformation {
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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<URL, Integer> urlToFontMapping = new HashMap<URL, Integer>();
private List<Font> fonts = new ArrayList<Font>();
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;
}
}

View File

@@ -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);
}

View File

@@ -2,7 +2,13 @@ package com.flaremicro.flaretv.visualforecast.icons;
import java.awt.Graphics2D; import java.awt.Graphics2D;
public interface Icon { public abstract class Icon {
public boolean isAnimated();
public void drawIcon(Graphics2D g2d, float scale, int animationStep); 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);
} }

View File

@@ -5,6 +5,7 @@ import java.awt.geom.AffineTransform;
import com.flaremicro.flaretv.visualforecast.icons.impl.BlizzardIcon; import com.flaremicro.flaretv.visualforecast.icons.impl.BlizzardIcon;
import com.flaremicro.flaretv.visualforecast.icons.impl.CloudIcon; 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.LightningIcon;
import com.flaremicro.flaretv.visualforecast.icons.impl.LightningOverlay; import com.flaremicro.flaretv.visualforecast.icons.impl.LightningOverlay;
import com.flaremicro.flaretv.visualforecast.icons.impl.LightningStormIcon; import com.flaremicro.flaretv.visualforecast.icons.impl.LightningStormIcon;
@@ -18,27 +19,43 @@ import com.flaremicro.flaretv.visualforecast.icons.impl.SunIcon;
public class IconProvider { public class IconProvider {
public static final Icon[] INDEXED_ICONS = new Icon[64];
public static final Icon SUN = new SunIcon(); public static final Icon INVALID = registerIcon(setMainIcon(new InvalidIcon(0)));
public static final Icon CLOUD = new CloudIcon(); public static final Icon SUN = registerIcon(new SunIcon(1));
public static final Icon PARTLY_CLOUDY = new PartlyCloudyIcon(CLOUD, SUN); public static final Icon CLOUD = registerIcon(new CloudIcon(2));
public static final Icon CLOUDY_CLOUDY = new PartlyCloudyIcon(CLOUD, CLOUD); public static final Icon PARTLY_CLOUDY = registerIcon(new PartlyCloudyIcon(3, CLOUD, SUN));
public static final Icon RAIN_LIGHTEST = new RainIcon(2, 2F, CLOUD); public static final Icon CLOUDY_CLOUDY = registerIcon(new PartlyCloudyIcon(4, CLOUD, CLOUD));
public static final Icon RAIN_LIGHT = new RainIcon(3, 2F, CLOUD); public static final Icon RAIN_LIGHTEST = registerIcon(new RainIcon(5, 2, 2F, CLOUD));
public static final Icon RAIN = new RainIcon(3, 1F, CLOUD); public static final Icon RAIN_LIGHT = registerIcon(new RainIcon(6, 3, 2F, CLOUD));
public static final Icon RAIN_HEAVY = new RainIcon(4, 1F, CLOUD); public static final Icon RAIN = registerIcon(new RainIcon(7, 3, 1F, CLOUD));
public static final Icon RAIN_HEAVIEST = new RainIcon(5, 1F, CLOUD); public static final Icon RAIN_HEAVY = registerIcon(new RainIcon(8, 4, 1F, CLOUD));
public static final Icon RAIN_VANCOUVER = new RainIcon(6, 1F, CLOUD); public static final Icon RAIN_HEAVIEST = registerIcon(new RainIcon(9, 5, 1F, CLOUD));
public static final Icon SCATTERD_SHOWERS = new PartlyCloudyIcon(new RainIcon(2, 4F, CLOUD), SUN); public static final Icon RAIN_VANCOUVER = registerIcon(new RainIcon(10, 6, 1F, CLOUD));
public static final Icon SNOWFLAKE = new SnowflakeIcon(); public static final Icon SCATTERD_SHOWERS = registerIcon(new PartlyCloudyIcon(11, new RainIcon(-1, 2, 4F, CLOUD), SUN));
public static final Icon SNOW = new SnowIcon(CLOUD, SNOWFLAKE); public static final Icon SNOWFLAKE = registerIcon(new SnowflakeIcon(12));
public static final Icon BLIZZARD = new BlizzardIcon(CLOUD, SNOWFLAKE); public static final Icon SNOW = registerIcon(new SnowIcon(13, CLOUD, SNOWFLAKE));
public static final Icon RAIN_SNOW = new RainSnowIcon(RAIN_LIGHTEST, SNOWFLAKE, true); public static final Icon BLIZZARD = registerIcon(new BlizzardIcon(14, CLOUD, SNOWFLAKE));
public static final Icon FREEZING_RAIN = new RainSnowIcon(RAIN_LIGHT, SNOWFLAKE, false); public static final Icon RAIN_SNOW = registerIcon(new RainSnowIcon(15, RAIN_LIGHTEST, SNOWFLAKE, true));
public static final Icon LIGHTNING_BOLT = new LightningIcon(); public static final Icon FREEZING_RAIN = registerIcon(new RainSnowIcon(16, RAIN_LIGHT, SNOWFLAKE, false));
public static final Icon LIGHTNING_STORM = new LightningStormIcon(CLOUD, LIGHTNING_BOLT); public static final Icon LIGHTNING_BOLT = registerIcon(new LightningIcon(17));
public static final Icon SMALL_CLOUD = new SmallCloudIcon(); public static final Icon LIGHTNING_STORM = registerIcon(new LightningStormIcon(18, CLOUD, LIGHTNING_BOLT));
public static final Icon LIGHTNING_OVERLAY = new LightningOverlay(SMALL_CLOUD, LIGHTNING_BOLT, BLIZZARD); 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) public static void drawIcon(Graphics2D g2d, Icon icon, int x, int y, int scale, int animationStep)
{ {

View File

@@ -5,14 +5,15 @@ import java.awt.geom.AffineTransform;
import com.flaremicro.flaretv.visualforecast.icons.Icon; import com.flaremicro.flaretv.visualforecast.icons.Icon;
public class BlizzardIcon implements Icon { public class BlizzardIcon extends Icon {
private final Icon cloudIcon; private final Icon cloudIcon;
private final Icon snowflakeIcon; private final Icon snowflakeIcon;
public BlizzardIcon(Icon cloudIcon, Icon snowflakeIcon) public BlizzardIcon(int id, Icon cloudIcon, Icon snowflakeIcon)
{ {
super(id);
this.cloudIcon = cloudIcon; this.cloudIcon = cloudIcon;
this.snowflakeIcon = snowflakeIcon; this.snowflakeIcon = snowflakeIcon;
} }

View File

@@ -7,8 +7,8 @@ import java.awt.geom.Ellipse2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon; import com.flaremicro.flaretv.visualforecast.icons.Icon;
public class CloudIcon implements Icon { public class CloudIcon extends Icon {
Ellipse2D.Float[] cloudCircles = new Ellipse2D.Float[]{ private final Ellipse2D.Float[] cloudCircles = new Ellipse2D.Float[]{
new Ellipse2D.Float(0, 0.5F, 0.28F, 0.325F), 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.142F, 0.619F, 0.287F, 0.231F),
new Ellipse2D.Float(0.666F, 0.597F, 0.208F, 0.234F), 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.142F, 0.619F, 0.287F, 0.231F),
new Ellipse2D.Float(0.666F, 0.597F, 0.208F, 0.234F) 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.233F, 0.150F, 0.369F, 0.677F),
new Ellipse2D.Float(0.113F, 0.326F, 0.266F, 0.356F), 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.749F, 0.412F, 0.251F, 0.417F),
new Ellipse2D.Float(0.652F, 0.555F, 0.150F, 0.136F), 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.309F, 0.173F, 0.209F, 0.235F),
new Ellipse2D.Float(0.554F, 0.276F, 0.204F, 0.314F), new Ellipse2D.Float(0.554F, 0.276F, 0.204F, 0.314F),
new Ellipse2D.Float(0.770F, 0.440F, 0.204F, 0.235F), 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), 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.328F, 0.188F, 0.209F, 0.235F),
new Ellipse2D.Float(0.573F, 0.296F, 0.204F, 0.314F), new Ellipse2D.Float(0.573F, 0.296F, 0.204F, 0.314F),
new Ellipse2D.Float(0.789F, 0.456F, 0.204F, 0.235F), 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), new Ellipse2D.Float(0.288F, 0.476F, 0.314F, 0.235F),
}; };
public CloudIcon(int id)
{
super(id);
}
@Override @Override
public void drawIcon(Graphics2D g2d, float scale, int animationStep) { public void drawIcon(Graphics2D g2d, float scale, int animationStep) {

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -7,7 +7,7 @@ import java.awt.geom.Path2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon; 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 boltPath = new Path2D.Float();
Path2D.Float shinePath = new Path2D.Float(); Path2D.Float shinePath = new Path2D.Float();
@@ -39,8 +39,9 @@ public class LightningIcon implements Icon {
new Color(0xFFFF00), new Color(0xFFFF00),
}; };
public LightningIcon() public LightningIcon(int id)
{ {
super(id);
boltPath.moveTo(0.380, 0); boltPath.moveTo(0.380, 0);
boltPath.lineTo(0.680, 0); boltPath.lineTo(0.680, 0);
boltPath.lineTo(0.577, 0.206); boltPath.lineTo(0.577, 0.206);

View File

@@ -3,13 +3,14 @@ package com.flaremicro.flaretv.visualforecast.icons.impl;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon; import com.flaremicro.flaretv.visualforecast.icons.Icon;
public class LightningOverlay implements Icon { public class LightningOverlay extends Icon {
private final Icon boltIcon; private final Icon boltIcon;
private final Icon smallCloudIcon; private final Icon smallCloudIcon;
private final Icon weatherIcon; 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.smallCloudIcon = smallCloudIcon;
this.boltIcon = boltIcon; this.boltIcon = boltIcon;
this.weatherIcon = weatherIcon; this.weatherIcon = weatherIcon;

View File

@@ -4,13 +4,14 @@ import java.awt.BasicStroke;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon; import com.flaremicro.flaretv.visualforecast.icons.Icon;
public class LightningStormIcon implements Icon { public class LightningStormIcon extends Icon {
private final Icon boltIcon; private final Icon boltIcon;
private final Icon cloudIcon; private final Icon cloudIcon;
public LightningStormIcon(Icon cloudIcon, Icon boltIcon) public LightningStormIcon(int id, Icon cloudIcon, Icon boltIcon)
{ {
super(id);
this.cloudIcon = cloudIcon; this.cloudIcon = cloudIcon;
this.boltIcon = boltIcon; this.boltIcon = boltIcon;

View File

@@ -4,12 +4,13 @@ import java.awt.Graphics2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon; import com.flaremicro.flaretv.visualforecast.icons.Icon;
public class PartlyCloudyIcon implements Icon { public class PartlyCloudyIcon extends Icon {
private Icon cloud; private Icon cloud;
private Icon sun; private Icon sun;
public PartlyCloudyIcon(Icon cloud, Icon sun) public PartlyCloudyIcon(int id, Icon cloud, Icon sun)
{ {
super(id);
this.cloud = cloud; this.cloud = cloud;
this.sun = sun; this.sun = sun;
} }

View File

@@ -7,7 +7,7 @@ import java.awt.geom.Path2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon; import com.flaremicro.flaretv.visualforecast.icons.Icon;
public class RainIcon implements Icon { public class RainIcon extends Icon {
private final int rainCount; private final int rainCount;
private final float rainSpace; private final float rainSpace;
private final Icon cloudIcon; private final Icon cloudIcon;
@@ -28,8 +28,9 @@ public class RainIcon implements Icon {
new Color(0x0066FF), 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.rainCount = rainCount;
this.rainSpace = rainSpace * 0.125F; this.rainSpace = rainSpace * 0.125F;
this.cloudIcon = cloudIcon; this.cloudIcon = cloudIcon;

View File

@@ -3,15 +3,16 @@ package com.flaremicro.flaretv.visualforecast.icons.impl;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon; import com.flaremicro.flaretv.visualforecast.icons.Icon;
public class RainSnowIcon implements Icon { public class RainSnowIcon extends Icon {
private final Icon rainIcon; private final Icon rainIcon;
private final Icon snowflakeIcon; private final Icon snowflakeIcon;
private final boolean snow; 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.rainIcon = rainIcon;
this.snowflakeIcon = snowflakeIcon; this.snowflakeIcon = snowflakeIcon;
this.snow = snow; this.snow = snow;

View File

@@ -6,8 +6,13 @@ import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D; import java.awt.geom.Ellipse2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon; import com.flaremicro.flaretv.visualforecast.icons.Icon;
public class SmallCloudIcon implements Icon { public class SmallCloudIcon extends Icon {
Ellipse2D.Float[] cloudCircles = new Ellipse2D.Float[]{ 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.456F, 0.241F, 0.346F, 0.748F),
new Ellipse2D.Float(0.655F, 0.238F, 0.356F, 0.748F), new Ellipse2D.Float(0.655F, 0.238F, 0.356F, 0.748F),
new Ellipse2D.Float(0.480F, 0.043F, 0.341F, 0.523F), 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) 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.196F, 0.052F, 0.439F, 0.748F),
new Ellipse2D.Float(0.030F, 0.230F, 0.439F, 0.654F), 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.709F, 0.300F, 0.218F, 0.335F),
new Ellipse2D.Float(0.429F, 0.498F, 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.183F, 0.124F, 0.478F, 0.713F),
new Ellipse2D.Float(0.040F, 0.264F, 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), new Ellipse2D.Float(0.716F, 0.335F, 0.237F, 0.365F),

View File

@@ -5,14 +5,15 @@ import java.awt.geom.AffineTransform;
import com.flaremicro.flaretv.visualforecast.icons.Icon; import com.flaremicro.flaretv.visualforecast.icons.Icon;
public class SnowIcon implements Icon { public class SnowIcon extends Icon {
private final Icon cloudIcon; private final Icon cloudIcon;
private final Icon snowflakeIcon; private final Icon snowflakeIcon;
public SnowIcon(Icon cloudIcon, Icon snowflakeIcon) public SnowIcon(int id, Icon cloudIcon, Icon snowflakeIcon)
{ {
super(id);
this.cloudIcon = cloudIcon; this.cloudIcon = cloudIcon;
this.snowflakeIcon = snowflakeIcon; this.snowflakeIcon = snowflakeIcon;
} }

View File

@@ -7,7 +7,7 @@ import java.awt.geom.Path2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon; 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 flakePath = new Path2D.Float();
Path2D.Float gradPath = new Path2D.Float(); Path2D.Float gradPath = new Path2D.Float();
Path2D.Float trianglePath = new Path2D.Float(); Path2D.Float trianglePath = new Path2D.Float();
@@ -27,8 +27,9 @@ public class SnowflakeIcon implements Icon {
new Color(0x2288FF), new Color(0x2288FF),
}; };
public SnowflakeIcon() public SnowflakeIcon(int id)
{ {
super(id);
flakePath.moveTo(0.400, 0); flakePath.moveTo(0.400, 0);
flakePath.lineTo(0.600, 0); flakePath.lineTo(0.600, 0);
flakePath.lineTo(0.600, 0.327); flakePath.lineTo(0.600, 0.327);

View File

@@ -8,7 +8,7 @@ import java.awt.geom.Path2D;
import com.flaremicro.flaretv.visualforecast.icons.Icon; import com.flaremicro.flaretv.visualforecast.icons.Icon;
public class SunIcon implements Icon { public class SunIcon extends Icon {
Path2D.Float sunPath = new Path2D.Float(); Path2D.Float sunPath = new Path2D.Float();
Ellipse2D.Float sunCircle1 = new Ellipse2D.Float(0.2F, 0.2F, 0.6F, 0.6F); 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); 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, 140, 0),
new Color(255, 120, 0), new Color(255, 120, 0),
}; };
public SunIcon() public SunIcon(int id)
{ {
super(id);
sunPath.moveTo(0.5F, 0.0F); sunPath.moveTo(0.5F, 0.0F);
sunPath.lineTo(0.605F, 0.106F); sunPath.lineTo(0.605F, 0.106F);
sunPath.lineTo(0.750F, 0.067F); sunPath.lineTo(0.750F, 0.067F);