???
This commit is contained in:
37
src/com/flaremicro/flaretv/visualforecast/Executor.java
Normal file
37
src/com/flaremicro/flaretv/visualforecast/Executor.java
Normal file
@@ -0,0 +1,37 @@
|
||||
package com.flaremicro.flaretv.visualforecast;
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.flaremicro.flaretv.visualforecast.interfaces.Tickable;
|
||||
|
||||
public class Executor {
|
||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
|
||||
private final Tickable tickable;
|
||||
private final long sleepNanos;
|
||||
|
||||
//private long nextTick = 0;
|
||||
|
||||
Executor(Tickable tickable, long sleepNanos) {
|
||||
this.tickable = tickable;
|
||||
this.sleepNanos = sleepNanos;
|
||||
}
|
||||
|
||||
Executor(Tickable tickable, int ticksPerSecond) {
|
||||
this(tickable, (long) ((1 / (double) ticksPerSecond) * 1000000000L));
|
||||
}
|
||||
|
||||
public void end() {
|
||||
scheduler.shutdown();
|
||||
}
|
||||
|
||||
public void begin() {
|
||||
scheduler.scheduleAtFixedRate(new Runnable() {
|
||||
public void run() {
|
||||
tickable.tick();
|
||||
}
|
||||
}, 0, sleepNanos, TimeUnit.NANOSECONDS);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.flaremicro.flaretv.visualforecast;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.flaremicro.util.Util;
|
||||
|
||||
public class PropertyManager {
|
||||
private final Properties underlyingProperties = new Properties();
|
||||
private static File propFile = new File("./vf1000.properties");
|
||||
|
||||
public boolean load() {
|
||||
Reader reader = null;
|
||||
try
|
||||
{
|
||||
reader = new FileReader(propFile);
|
||||
underlyingProperties.load(reader);
|
||||
return true;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Util.cleanClose(reader);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean store() {
|
||||
Writer writer = null;
|
||||
try
|
||||
{
|
||||
writer = new FileWriter(propFile);
|
||||
underlyingProperties.store(writer, "VisualForecast 1000 Properties file. Functional provider must be set for successful boot!");
|
||||
return true;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally{
|
||||
Util.cleanClose(writer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,10 @@ import static com.flaremicro.flaretv.visualforecast.graphics.RenderConstants.*;
|
||||
|
||||
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;
|
||||
import com.flaremicro.flaretv.visualforecast.providerapi.MockForecastProvider;
|
||||
|
||||
public class RenderPanel extends JPanel implements Tickable, ComponentListener {
|
||||
|
||||
@@ -42,15 +42,17 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
|
||||
private long ticks = 0;
|
||||
|
||||
private Rectangle redrawBound = new Rectangle(0, 0, 1, 1);
|
||||
private Rectangle exclusiveRedrawBound = null;
|
||||
|
||||
private String currentTown = "";
|
||||
private String currentForecast = "";
|
||||
|
||||
public RenderPanel() {
|
||||
this.addComponentListener(this);
|
||||
this.setDoubleBuffered(true);
|
||||
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();
|
||||
//new Thread(new TickThread(this, 30)).start();
|
||||
}
|
||||
|
||||
private Graphics2D prepareFrameBuffer() {
|
||||
@@ -166,19 +168,30 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
|
||||
return frameBuffer.getSnapshot();
|
||||
}
|
||||
|
||||
public void addRedrawBound(int x, int y, int w, int h) {
|
||||
private void addRedrawBound(int x, int y, int w, int h, boolean isExclusive){
|
||||
|
||||
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(isExclusive)
|
||||
this.exclusiveRedrawBound = rect;
|
||||
if (redrawBound == null)
|
||||
this.redrawBound = new Rectangle((int) (x * wScale), (int) (y * hScale), (int) (w * wScale), (int) (h * hScale));
|
||||
else this.redrawBound.add(rect);
|
||||
}
|
||||
|
||||
public void addRedrawBound(int x, int y, int w, int h) {
|
||||
addRedrawBound(x, y, w, h, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void componentResized(ComponentEvent e) {
|
||||
loseRedrawRegion();
|
||||
}
|
||||
|
||||
public void loseRedrawRegion() {
|
||||
this.redrawBound = null;
|
||||
addRedrawBound(W - TIMEBAR_WIDTH + TIMEBAR_OFFSET, TIMEBAR_Y, TIMEBAR_WIDTH, TIMEBAR_HEIGHT);
|
||||
addRedrawBound(W - TIMEBAR_WIDTH + TIMEBAR_OFFSET, TIMEBAR_Y, TIMEBAR_WIDTH, TIMEBAR_HEIGHT, false);
|
||||
if (this.currentFlavour != null)
|
||||
this.currentFlavour.redrawRegionlost(this);
|
||||
}
|
||||
@@ -214,10 +227,18 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
|
||||
this.currentForecast = currentForecast;
|
||||
}
|
||||
|
||||
public void setFullRepaint() {
|
||||
public void requestFullRepaint() {
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void requestBoundedRepaint() {
|
||||
repaint(redrawBound);
|
||||
}
|
||||
|
||||
public void requestExclusiveBoundedRepaint() {
|
||||
repaint(exclusiveRedrawBound);
|
||||
}
|
||||
|
||||
/*@Override
|
||||
public void run() {
|
||||
while (true)
|
||||
|
||||
@@ -25,6 +25,7 @@ public class TickThread implements Runnable {
|
||||
}
|
||||
|
||||
public void run() {
|
||||
long nanosLost = 0;
|
||||
while (running) {
|
||||
/*while(System.nanoTime() < nextTick)
|
||||
{
|
||||
@@ -39,12 +40,12 @@ public class TickThread implements Runnable {
|
||||
}
|
||||
nextTick = System.nanoTime() + sleepNanos;
|
||||
tickable.tick();*/
|
||||
long nanosLost = System.nanoTime();
|
||||
tickable.tick();
|
||||
nanosLost -= System.nanoTime();
|
||||
//Unnecessary conditional?
|
||||
//if(sleepNanos+nanosLost > 0)
|
||||
LockSupport.parkNanos(sleepNanos+nanosLost);
|
||||
nanosLost = System.nanoTime();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,16 +2,26 @@ package com.flaremicro.flaretv.visualforecast;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowListener;
|
||||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
public class VisualForecastFrame extends JFrame {
|
||||
import com.flaremicro.flaretv.visualforecast.providerapi.ForecastProviderManager;
|
||||
|
||||
public class VisualForecastFrame extends JFrame implements WindowListener, KeyListener{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1L;
|
||||
private RenderPanel contentPane;
|
||||
private RenderPanel renderPane;
|
||||
private ForecastProviderManager forecastProviderManager;
|
||||
private Executor executor;
|
||||
private PropertyManager propertyManager;
|
||||
private boolean isFullscreen = false;
|
||||
|
||||
/**
|
||||
* Launch the application.
|
||||
@@ -22,6 +32,9 @@ public class VisualForecastFrame extends JFrame {
|
||||
try {
|
||||
VisualForecastFrame frame = new VisualForecastFrame();
|
||||
frame.setVisible(true);
|
||||
frame.init();
|
||||
//GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[1].setFullScreenWindow(frame);
|
||||
frame.createBufferStrategy(2);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -29,17 +42,108 @@ public class VisualForecastFrame extends JFrame {
|
||||
});
|
||||
}
|
||||
|
||||
public void end()
|
||||
{
|
||||
if(executor != null)
|
||||
executor.end();
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
end();
|
||||
executor = new Executor(this.renderPane, 30);
|
||||
executor.begin();
|
||||
|
||||
forecastProviderManager = new ForecastProviderManager();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the frame.
|
||||
*/
|
||||
public VisualForecastFrame() {
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
setBounds(100, 100, 640*2, 480*2);
|
||||
contentPane = new RenderPanel();
|
||||
contentPane.setBorder(null);
|
||||
contentPane.setLayout(new BorderLayout(0, 0));
|
||||
setContentPane(contentPane);
|
||||
renderPane = new RenderPanel();
|
||||
renderPane.setBorder(null);
|
||||
renderPane.setLayout(new BorderLayout(0, 0));
|
||||
setContentPane(renderPane);
|
||||
setUndecorated(true);
|
||||
addWindowListener(this);
|
||||
addKeyListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowOpened(WindowEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e) {
|
||||
|
||||
end();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowClosed(WindowEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowIconified(WindowEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeiconified(WindowEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowActivated(WindowEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void windowDeactivated(WindowEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(KeyEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed(KeyEvent e) {
|
||||
if(e.getKeyCode() == KeyEvent.VK_F11)
|
||||
{
|
||||
if(isFullscreen)
|
||||
{
|
||||
isFullscreen = false;
|
||||
this.getGraphicsConfiguration().getDevice().setFullScreenWindow(null);
|
||||
setBounds(100, 100, 640*2, 480*2);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
isFullscreen = true;
|
||||
this.getGraphicsConfiguration().getDevice().setFullScreenWindow(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased(KeyEvent e) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,12 +2,14 @@ package com.flaremicro.flaretv.visualforecast.flavour;
|
||||
|
||||
import static com.flaremicro.flaretv.visualforecast.graphics.RenderConstants.MAINBAR_HEIGHT;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
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.Transparency;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
@@ -28,11 +30,14 @@ public class DayForecastFlavour implements Flavour {
|
||||
private Font smallFont;
|
||||
private ForecastDetails details;
|
||||
private TownForecast currentTown = null;
|
||||
private TownForecast previousTown = null;
|
||||
private int townIndex;
|
||||
|
||||
private BufferedImage lastBound = null;
|
||||
private BufferedImage mainBound = null;
|
||||
private BufferedImage prevBound = null;
|
||||
|
||||
private int ticksBeforeChange = 200;
|
||||
private int animationTicks = -1;
|
||||
|
||||
public DayForecastFlavour() {
|
||||
font = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf"));
|
||||
@@ -41,26 +46,62 @@ public class DayForecastFlavour implements Flavour {
|
||||
|
||||
@Override
|
||||
public void tick(RenderPanel renderer, long ticks, int iconTicks) {
|
||||
ticksBeforeChange--;
|
||||
if (ticksBeforeChange < 0)
|
||||
if(animationTicks >= 0)
|
||||
{
|
||||
ticksBeforeChange = 200;
|
||||
dayOffset = dayOffset + 4;
|
||||
if (dayOffset >= 8)
|
||||
animationTicks += 8;
|
||||
if(animationTicks > RenderConstants.W - 60)
|
||||
{
|
||||
dayOffset = 0;
|
||||
townIndex++;
|
||||
if (townIndex >= details.getTownForecast().length)
|
||||
{
|
||||
renderer.nextFlavour();
|
||||
}
|
||||
else
|
||||
{
|
||||
currentTown = details.getTownForecast()[townIndex];
|
||||
renderer.setCurrentTown(currentTown.getTownName());
|
||||
}
|
||||
animationTicks = -1;
|
||||
prevBound.flush();
|
||||
prevBound = null;
|
||||
renderer.requestFullRepaint();
|
||||
renderer.loseRedrawRegion();
|
||||
}
|
||||
else renderer.requestExclusiveBoundedRepaint();
|
||||
}
|
||||
else
|
||||
{
|
||||
ticksBeforeChange--;
|
||||
if (ticksBeforeChange < 0)
|
||||
{
|
||||
animationTicks = 0;
|
||||
if(prevBound != null)
|
||||
prevBound.flush();
|
||||
if(mainBound != null)
|
||||
mainBound.flush();
|
||||
prevBound = renderer.getGraphicsConfiguration().createCompatibleImage(526, MAINBAR_HEIGHT - 28, Transparency.BITMASK);
|
||||
mainBound = renderer.getGraphicsConfiguration().createCompatibleImage(526, MAINBAR_HEIGHT - 28, Transparency.BITMASK);
|
||||
mainBound.setAccelerationPriority(1);
|
||||
prevBound.setAccelerationPriority(1);
|
||||
|
||||
ticksBeforeChange = 200;
|
||||
dayOffset = dayOffset + 4;
|
||||
if (dayOffset >= 8)
|
||||
{
|
||||
dayOffset = 0;
|
||||
townIndex++;
|
||||
if (townIndex >= details.getTownForecast().length)
|
||||
{
|
||||
renderer.nextFlavour();
|
||||
}
|
||||
else
|
||||
{
|
||||
previousTown = currentTown;
|
||||
currentTown = details.getTownForecast()[townIndex];
|
||||
renderer.setCurrentTown(currentTown.getTownName());
|
||||
}
|
||||
}
|
||||
|
||||
//Flicker workaround
|
||||
BufferedImage throwaway = new BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR);
|
||||
Graphics2D g2d = throwaway.createGraphics();
|
||||
this.drawFlavour(renderer, g2d, ticks, iconTicks);
|
||||
g2d.dispose();
|
||||
throwaway.flush();
|
||||
|
||||
renderer.loseRedrawRegion();
|
||||
renderer.requestFullRepaint();
|
||||
}
|
||||
renderer.setFullRepaint();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,78 +136,148 @@ public class DayForecastFlavour implements Flavour {
|
||||
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++)
|
||||
if(animationTicks < 0)
|
||||
{
|
||||
|
||||
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))
|
||||
drawTownForecast(g2d, currentTown, dayOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
Graphics2D gimg = prevBound.createGraphics();
|
||||
Graphics2D gimg2 = mainBound.createGraphics();
|
||||
gimg.translate(-RenderConstants.SIDE_OFFSET+1, -RenderConstants.TOPBAR_HEIGHT - 14);
|
||||
gimg2.translate(-RenderConstants.SIDE_OFFSET+1, -RenderConstants.TOPBAR_HEIGHT - 14);
|
||||
gimg.setStroke(new BasicStroke(2));
|
||||
gimg2.setStroke(new BasicStroke(2));
|
||||
if(dayOffset == 0)
|
||||
{
|
||||
statLine1 = "MISSING";
|
||||
statLine2 = "DATA";
|
||||
drawTownForecast(gimg, previousTown, dayOffset + 4);
|
||||
drawTownForecast(gimg2, currentTown, dayOffset);
|
||||
} else {
|
||||
drawTownForecast(gimg, currentTown, dayOffset - 4);
|
||||
drawTownForecast(gimg2, currentTown, dayOffset);
|
||||
}
|
||||
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);
|
||||
gimg.dispose();
|
||||
gimg2.dispose();
|
||||
|
||||
g2d.setClip(animationTicks + RenderConstants.SIDE_OFFSET, RenderConstants.TOPBAR_HEIGHT+14, 526-animationTicks, MAINBAR_HEIGHT - 28);
|
||||
g2d.drawImage(prevBound, RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT + 14, renderer);
|
||||
g2d.setClip(0, RenderConstants.TOPBAR_HEIGHT+15, animationTicks, MAINBAR_HEIGHT - 28);
|
||||
g2d.drawImage(mainBound, RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT + 14, renderer);
|
||||
g2d.setClip(null);
|
||||
|
||||
}
|
||||
}
|
||||
if(animationTicks < 0)
|
||||
{
|
||||
mainBound = renderer.getSnapshot().getSubimage(RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT + 14, 526, MAINBAR_HEIGHT - 28);
|
||||
mainBound.setAccelerationPriority(1);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawTownForecast(Graphics2D g2d, TownForecast townForecast, int dayOffset)
|
||||
{
|
||||
for (int i = 0; i < Math.min(4, townForecast.getDayForecast().length - dayOffset); i++)
|
||||
{
|
||||
|
||||
DayForecast forecast = townForecast.getDayForecast()[i + 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);
|
||||
|
||||
if (!ValueCheck.valueNoData(forecast.hiTemp) && !ValueCheck.valueNoData(forecast.loTemp))
|
||||
{
|
||||
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);
|
||||
}
|
||||
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++)
|
||||
if(animationTicks < 0)
|
||||
{
|
||||
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);
|
||||
g2d.drawImage(mainBound, RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT + 14, renderer);
|
||||
drawIcons(g2d, currentTown, dayOffset, iconTicks);
|
||||
}
|
||||
else
|
||||
{
|
||||
g2d.setClip(animationTicks + RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT+14, 526, MAINBAR_HEIGHT - 28);
|
||||
g2d.drawImage(prevBound, RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT + 14, renderer);
|
||||
if(dayOffset == 0)
|
||||
{
|
||||
drawIcons(g2d, previousTown, dayOffset + 4, iconTicks);
|
||||
g2d.setClip(0, RenderConstants.TOPBAR_HEIGHT+14, animationTicks, MAINBAR_HEIGHT - 28);
|
||||
g2d.drawImage(mainBound, RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT + 14, renderer);
|
||||
drawIcons(g2d, currentTown, dayOffset, iconTicks);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawIcons(g2d, currentTown, dayOffset - 4, iconTicks);
|
||||
g2d.setClip(0, RenderConstants.TOPBAR_HEIGHT+14, animationTicks, MAINBAR_HEIGHT - 28);
|
||||
g2d.drawImage(mainBound, RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT + 14, renderer);
|
||||
drawIcons(g2d, currentTown, dayOffset, iconTicks);
|
||||
}
|
||||
g2d.setClip(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawIcons(Graphics2D g2d, TownForecast currentTown, int dayOffset, int iconTicks){
|
||||
|
||||
for (int i = 0; i < Math.min(4, currentTown.getDayForecast().length - dayOffset); i++)
|
||||
{
|
||||
DayForecast forecast = currentTown.getDayForecast()[i + 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);
|
||||
if(animationTicks >= 0)
|
||||
renderer.addRedrawBound(0, RenderConstants.TOPBAR_HEIGHT, RenderConstants.W, RenderConstants.MAINBAR_HEIGHT);
|
||||
else
|
||||
renderer.addRedrawBound(RenderConstants.SIDE_OFFSET + 24, RenderConstants.TOPBAR_HEIGHT + 60, 604, 84);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
package com.flaremicro.flaretv.visualforecast.flavour;
|
||||
|
||||
import static com.flaremicro.flaretv.visualforecast.graphics.RenderConstants.MAINBAR_HEIGHT;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
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.Transparency;
|
||||
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 DayForecastFlavourOldAnimation implements Flavour {
|
||||
private int dayOffset = 0;
|
||||
private Font font;
|
||||
private Font smallFont;
|
||||
private ForecastDetails details;
|
||||
private TownForecast currentTown = null;
|
||||
private TownForecast previousTown = null;
|
||||
private int townIndex;
|
||||
|
||||
private BufferedImage lastBound = null;
|
||||
|
||||
private int ticksBeforeChange = 200;
|
||||
private int animationTicks = -1;
|
||||
|
||||
public DayForecastFlavourOldAnimation() {
|
||||
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) {
|
||||
if(animationTicks >= 0)
|
||||
{
|
||||
animationTicks += 8;
|
||||
if(animationTicks > RenderConstants.W - 60)
|
||||
{
|
||||
animationTicks = -1;
|
||||
renderer.requestFullRepaint();
|
||||
renderer.loseRedrawRegion();
|
||||
}
|
||||
else renderer.requestExclusiveBoundedRepaint();
|
||||
}
|
||||
else
|
||||
{
|
||||
ticksBeforeChange--;
|
||||
if (ticksBeforeChange < 0)
|
||||
{
|
||||
animationTicks = 0;
|
||||
lastBound = renderer.getGraphicsConfiguration().createCompatibleImage(526*2+RenderConstants.SIDE_OFFSET, MAINBAR_HEIGHT - 28, Transparency.BITMASK);
|
||||
lastBound.setAccelerationPriority(1);
|
||||
ticksBeforeChange = 200;
|
||||
dayOffset = dayOffset + 4;
|
||||
if (dayOffset >= 8)
|
||||
{
|
||||
dayOffset = 0;
|
||||
townIndex++;
|
||||
if (townIndex >= details.getTownForecast().length)
|
||||
{
|
||||
renderer.nextFlavour();
|
||||
}
|
||||
else
|
||||
{
|
||||
previousTown = currentTown;
|
||||
currentTown = details.getTownForecast()[townIndex];
|
||||
renderer.setCurrentTown(currentTown.getTownName());
|
||||
}
|
||||
}
|
||||
renderer.loseRedrawRegion();
|
||||
renderer.requestFullRepaint();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@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
|
||||
{
|
||||
if(animationTicks < 0)
|
||||
{
|
||||
drawTownForecast(g2d, currentTown, dayOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
Graphics2D gimg = lastBound.createGraphics();
|
||||
gimg.translate(-RenderConstants.SIDE_OFFSET+1, -RenderConstants.TOPBAR_HEIGHT - 14);
|
||||
gimg.setStroke(new BasicStroke(2));
|
||||
if(dayOffset == 0)
|
||||
{
|
||||
drawTownForecast(gimg, previousTown, dayOffset + 4);
|
||||
gimg.translate(RenderConstants.W - (RenderConstants.SIDE_OFFSET), 0);
|
||||
drawTownForecast(gimg, currentTown, dayOffset);
|
||||
gimg.translate(RenderConstants.SIDE_OFFSET - RenderConstants.W, 0);
|
||||
} else {
|
||||
drawTownForecast(gimg, currentTown, dayOffset - 4);
|
||||
gimg.translate(RenderConstants.W - (RenderConstants.SIDE_OFFSET), 0);
|
||||
drawTownForecast(gimg, currentTown, dayOffset);
|
||||
gimg.translate(RenderConstants.SIDE_OFFSET - RenderConstants.W, 0);
|
||||
}
|
||||
gimg.dispose();
|
||||
|
||||
g2d.translate(-animationTicks, 0);
|
||||
g2d.drawImage(lastBound, RenderConstants.SIDE_OFFSET, RenderConstants.TOPBAR_HEIGHT + 15, renderer);
|
||||
g2d.translate(animationTicks, 0);
|
||||
}
|
||||
}
|
||||
if(animationTicks < 0)
|
||||
{
|
||||
lastBound = renderer.getSnapshot().getSubimage(RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT + 14, 526, MAINBAR_HEIGHT - 28);
|
||||
lastBound.setAccelerationPriority(1);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawTownForecast(Graphics2D g2d, TownForecast townForecast, int dayOffset)
|
||||
{
|
||||
for (int i = 0; i < Math.min(4, townForecast.getDayForecast().length - dayOffset); i++)
|
||||
{
|
||||
|
||||
DayForecast forecast = townForecast.getDayForecast()[i + 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);
|
||||
|
||||
if (!ValueCheck.valueNoData(forecast.hiTemp) && !ValueCheck.valueNoData(forecast.loTemp))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBoundLimitedFlavour(RenderPanel renderer, Graphics2D g2d, Rectangle bounds, long ticks, int iconTicks) {
|
||||
if (details != null && currentTown != null && currentTown.getDayForecast() != null && currentTown.getDayForecast().length > 0)
|
||||
{
|
||||
if(animationTicks < 0)
|
||||
{
|
||||
g2d.drawImage(lastBound, RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT + 14, renderer);
|
||||
drawIcons(g2d, currentTown, dayOffset, iconTicks);
|
||||
}
|
||||
else
|
||||
{
|
||||
g2d.translate(-animationTicks, 0);
|
||||
g2d.drawImage(lastBound, RenderConstants.SIDE_OFFSET-1, RenderConstants.TOPBAR_HEIGHT + 14, renderer);
|
||||
if(dayOffset == 0)
|
||||
{
|
||||
|
||||
drawIcons(g2d, previousTown, dayOffset + 4, iconTicks);
|
||||
g2d.translate(RenderConstants.W - (RenderConstants.SIDE_OFFSET), 0);
|
||||
drawIcons(g2d, currentTown, dayOffset, iconTicks);
|
||||
}
|
||||
else
|
||||
{
|
||||
drawIcons(g2d, currentTown, dayOffset - 4, iconTicks);
|
||||
g2d.translate(RenderConstants.W - (RenderConstants.SIDE_OFFSET), 0);
|
||||
drawIcons(g2d, currentTown, dayOffset, iconTicks);
|
||||
}
|
||||
g2d.translate(animationTicks + (RenderConstants.SIDE_OFFSET) - RenderConstants.W, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawIcons(Graphics2D g2d, TownForecast currentTown, int dayOffset, int iconTicks){
|
||||
|
||||
for (int i = 0; i < Math.min(4, currentTown.getDayForecast().length - dayOffset); i++)
|
||||
{
|
||||
DayForecast forecast = currentTown.getDayForecast()[i + 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) {
|
||||
if(animationTicks >= 0)
|
||||
renderer.addRedrawBound(0, RenderConstants.TOPBAR_HEIGHT, RenderConstants.W, RenderConstants.MAINBAR_HEIGHT);
|
||||
else
|
||||
renderer.addRedrawBound(RenderConstants.SIDE_OFFSET + 24, RenderConstants.TOPBAR_HEIGHT + 60, 604, 84);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ public class DayForecast {
|
||||
public DayForecast(byte hiTemp, byte loTemp, byte iconId, String weatherLine1, String weatherLine2, float percipPercent){
|
||||
this.hiTemp = hiTemp;
|
||||
this.loTemp = loTemp;
|
||||
this.iconId = iconId;
|
||||
this.iconId = (byte)(iconId & 63);
|
||||
this.weatherLine1 = weatherLine1;
|
||||
this.weatherLine2 = weatherLine2;
|
||||
this.percipPercent = percipPercent;
|
||||
|
||||
@@ -4,7 +4,10 @@ import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
import com.flaremicro.flaretv.visualforecast.icons.impl.BlizzardIcon;
|
||||
import com.flaremicro.flaretv.visualforecast.icons.impl.ButterIcon;
|
||||
import com.flaremicro.flaretv.visualforecast.icons.impl.CloudIcon;
|
||||
import com.flaremicro.flaretv.visualforecast.icons.impl.FogIcon;
|
||||
import com.flaremicro.flaretv.visualforecast.icons.impl.IceCubeIcon;
|
||||
import com.flaremicro.flaretv.visualforecast.icons.impl.InvalidIcon;
|
||||
import com.flaremicro.flaretv.visualforecast.icons.impl.LightningIcon;
|
||||
import com.flaremicro.flaretv.visualforecast.icons.impl.LightningOverlay;
|
||||
@@ -43,6 +46,12 @@ public class IconProvider {
|
||||
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));
|
||||
public static final Icon FOG = registerIcon(new FogIcon(22, CLOUD));
|
||||
public static final Icon ICE_CUBE = registerIcon(new IceCubeIcon(23));
|
||||
public static final Icon HAIL = registerIcon(new BlizzardIcon(24, CLOUD, ICE_CUBE));
|
||||
public static final Icon BUTTER = registerIcon(new ButterIcon(25));
|
||||
public static final Icon BUTTER_RAIN = registerIcon(new BlizzardIcon(26, CLOUD, BUTTER));
|
||||
//public static final Icon INVALID_RAIN = registerIcon(new LightningOverlay(27, SUN, BUTTER, new BlizzardIcon(-1, LIGHTNING_BOLT, INVALID)));
|
||||
|
||||
private static Icon registerIcon(Icon icon)
|
||||
{
|
||||
|
||||
@@ -25,11 +25,11 @@ public class BlizzardIcon extends Icon {
|
||||
g2d.translate(0, 3);
|
||||
snowflakeIcon.drawIcon(g2d, scale*0.25F, animationStep);
|
||||
g2d.translate(1, -1);
|
||||
snowflakeIcon.drawIcon(g2d, scale*0.25F, animationStep);
|
||||
snowflakeIcon.drawIcon(g2d, scale*0.25F, animationStep+1);
|
||||
g2d.translate(1, 1);
|
||||
snowflakeIcon.drawIcon(g2d, scale*0.25F, animationStep);
|
||||
snowflakeIcon.drawIcon(g2d, scale*0.25F, animationStep+2);
|
||||
g2d.translate(1, -1);
|
||||
snowflakeIcon.drawIcon(g2d, scale*0.25F, animationStep);
|
||||
snowflakeIcon.drawIcon(g2d, scale*0.25F, animationStep+3);
|
||||
g2d.setTransform(af);
|
||||
g2d.translate(0F, -0.10F);
|
||||
g2d.scale(1F, 0.8F);
|
||||
@@ -37,7 +37,7 @@ public class BlizzardIcon extends Icon {
|
||||
g2d.setTransform(af);
|
||||
g2d.translate(0.3F, 0);
|
||||
g2d.scale(0.7F, 0.7F);
|
||||
snowflakeIcon.drawIcon(g2d, scale*0.7F, animationStep);
|
||||
snowflakeIcon.drawIcon(g2d, scale*0.7F, animationStep+4);
|
||||
g2d.setTransform(af);
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.flaremicro.flaretv.visualforecast.icons.impl;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
|
||||
import com.flaremicro.flaretv.visualforecast.icons.Icon;
|
||||
|
||||
public class ButterIcon extends Icon {
|
||||
|
||||
Path2D.Float iceOutline = new Path2D.Float();
|
||||
|
||||
Path2D.Float[] iceFaces = new Path2D.Float[3];
|
||||
Path2D.Float[] iceShines = new Path2D.Float[3];
|
||||
|
||||
Color[] iceFaceColors = new Color[] {
|
||||
new Color(0xfff8a0),
|
||||
new Color(0xfff14c),
|
||||
new Color(0xccbc00),
|
||||
};
|
||||
Color[] iceShineAnimation = new Color[] {
|
||||
new Color(0xFFFFFF),
|
||||
};
|
||||
|
||||
public ButterIcon(int id) {
|
||||
super(id);
|
||||
|
||||
iceOutline.moveTo(0F, 0.161F);
|
||||
iceOutline.lineTo(0.542F, 0F);
|
||||
iceOutline.lineTo(1.0F, 0.093F);
|
||||
iceOutline.lineTo(1.0F, 0.441F);
|
||||
iceOutline.lineTo(0.489F, 0.650F);
|
||||
iceOutline.lineTo(0.0F, 0.531F);
|
||||
iceOutline.closePath();
|
||||
|
||||
iceFaces[1] = new Path2D.Float();
|
||||
iceFaces[1].moveTo(0F, 0.161F);
|
||||
iceFaces[1].lineTo(0.542F, 0F);
|
||||
iceFaces[1].lineTo(1.0F, 0.093F);
|
||||
iceFaces[1].lineTo(0.489F, 0.263F);
|
||||
iceFaces[1].closePath();
|
||||
|
||||
iceFaces[2] = new Path2D.Float();
|
||||
iceFaces[2].moveTo(0.489F, 0.263F);
|
||||
iceFaces[2].lineTo(1.0F, 0.093F);
|
||||
iceFaces[2].lineTo(1.0F, 0.441F);
|
||||
iceFaces[2].lineTo(0.489F, 0.650F);
|
||||
iceFaces[2].closePath();
|
||||
|
||||
iceFaces[0] = new Path2D.Float();
|
||||
iceFaces[0].moveTo(0.0F, 0.161F);
|
||||
iceFaces[0].lineTo(0.489F, 0.263F);
|
||||
iceFaces[0].lineTo(0.489F, 0.650F);
|
||||
iceFaces[0].lineTo(0.0F, 0.531F);
|
||||
iceFaces[0].closePath();
|
||||
|
||||
iceShines[1] = new Path2D.Float();
|
||||
iceShines[1].moveTo(0.537F, 0.013F);
|
||||
iceShines[1].lineTo(0.930F, 0.099F);
|
||||
iceShines[1].lineTo(0.673F, 0.185F);
|
||||
iceShines[1].lineTo(0.556F, 0.187F);
|
||||
iceShines[1].lineTo(0.556F, 0.187F);
|
||||
iceShines[1].lineTo(0.742F, 0.086);
|
||||
iceShines[1].closePath();
|
||||
|
||||
iceShines[2] = new Path2D.Float();
|
||||
iceShines[2].moveTo(0.981F, 0.134F);
|
||||
iceShines[2].lineTo(0.981F, 0.423F);
|
||||
iceShines[2].lineTo(0.515F, 0.624F);
|
||||
iceShines[2].lineTo(0.571F, 0.557F);
|
||||
iceShines[2].lineTo(0.915F, 0.372F);
|
||||
iceShines[2].closePath();
|
||||
|
||||
iceShines[0] = new Path2D.Float();
|
||||
iceShines[0].moveTo(0.018F, 0.187F);
|
||||
iceShines[0].lineTo(0.205F, 0.229F);
|
||||
iceShines[0].lineTo(0.060F, 0.249F);
|
||||
iceShines[0].lineTo(0.044F, 0.475F);
|
||||
iceShines[0].lineTo(0.021F, 0.508F);
|
||||
iceShines[0].closePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawIcon(Graphics2D g2d, float scale, int animationStep) {
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.setStroke(new BasicStroke(4 / scale));
|
||||
g2d.translate(0F, 0.325F);
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.draw(iceOutline);
|
||||
for(int i = 0; i < iceFaces.length; i++)
|
||||
{
|
||||
g2d.setColor(iceFaceColors[i]);
|
||||
g2d.fill(iceFaces[i]);
|
||||
g2d.setColor(iceShineAnimation[(i+animationStep) % iceShineAnimation.length]);
|
||||
g2d.fill(iceShines[i]);
|
||||
}
|
||||
g2d.translate(0F, -0.325F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnimated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.flaremicro.flaretv.visualforecast.icons.impl;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
|
||||
import com.flaremicro.flaretv.visualforecast.icons.Icon;
|
||||
|
||||
public class FogIcon extends Icon {
|
||||
private final Icon cloudIcon;
|
||||
|
||||
private Path2D fogPath = new Path2D.Float();
|
||||
|
||||
Color[] aniColor = {
|
||||
new Color(0xC0C0C0),
|
||||
new Color(0xC8C8C8),
|
||||
new Color(0xD0D0D0),
|
||||
new Color(0xD8D8D8),
|
||||
new Color(0xD0D0D0),
|
||||
new Color(0xC8C8C8),
|
||||
new Color(0xC0C0C0),
|
||||
new Color(0xB8B8B8),
|
||||
new Color(0xB0B0B0),
|
||||
new Color(0xA8A8A8),
|
||||
new Color(0xB0B0B0),
|
||||
new Color(0xB8B8B8),
|
||||
};
|
||||
|
||||
|
||||
public FogIcon(int id, Icon cloudIcon)
|
||||
{
|
||||
super(id);
|
||||
this.cloudIcon = cloudIcon;
|
||||
fogPath.moveTo(0F, 0.1F);
|
||||
fogPath.curveTo(0F, 0.1F, 0.25F, 0F, 0.5F, 0.1F);
|
||||
fogPath.curveTo(0.5F, 0.1F, 0.75F, 0.2F, 1.0F, 0.1F);
|
||||
fogPath.lineTo(1F, 0.2F);
|
||||
fogPath.curveTo(1F, 0.2F, 0.75F, 0.3F, 0.5F, 0.2F);
|
||||
fogPath.curveTo(0.5F, 0.2F, 0.25F, 0.1F, 0F, 0.2F);
|
||||
fogPath.closePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawIcon(Graphics2D g2d, float scale, int animationStep) {
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
g2d.setStroke(new BasicStroke(4/scale));
|
||||
g2d.translate(0, 0.4F + 0.2F*i);
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.draw(fogPath);
|
||||
g2d.setColor(aniColor[(animationStep + i) % aniColor.length]);
|
||||
g2d.fill(fogPath);
|
||||
g2d.translate(0, -0.4F - 0.2*i);
|
||||
}
|
||||
//Fog?
|
||||
g2d.translate(0F, -0.10F);
|
||||
g2d.scale(1F, 0.8F);
|
||||
cloudIcon.drawIcon(g2d, scale, animationStep);
|
||||
g2d.scale(1F, 1.25F);
|
||||
g2d.translate(0F, 0.10F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnimated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package com.flaremicro.flaretv.visualforecast.icons.impl;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
|
||||
import com.flaremicro.flaretv.visualforecast.icons.Icon;
|
||||
|
||||
public class IceCubeIcon extends Icon {
|
||||
|
||||
Path2D.Float iceOutline = new Path2D.Float();
|
||||
|
||||
Path2D.Float[] iceFaces = new Path2D.Float[3];
|
||||
Path2D.Float[] iceShines = new Path2D.Float[3];
|
||||
|
||||
Path2D.Float iceBeams = new Path2D.Float();
|
||||
|
||||
Color[] iceFaceColors = new Color[] {
|
||||
new Color(0xb9dbff),
|
||||
new Color(0x92b1ff),
|
||||
new Color(0x3886ff),
|
||||
};
|
||||
Color[] iceShineAnimation = new Color[] {
|
||||
new Color(0x92B1FF),
|
||||
new Color(0xA2C1FF),
|
||||
new Color(0xB2D1FF),
|
||||
new Color(0xC2E1FF),
|
||||
new Color(0xD2F1FF),
|
||||
new Color(0xE2FFFF),
|
||||
new Color(0xFFFFFF),
|
||||
new Color(0xE2FFFF),
|
||||
new Color(0xD2F1FF),
|
||||
new Color(0xC2E1FF),
|
||||
new Color(0xB2D1FF),
|
||||
new Color(0xA2C1FF),
|
||||
};
|
||||
|
||||
public IceCubeIcon(int id) {
|
||||
super(id);
|
||||
|
||||
iceBeams.moveTo(0.15F, 0.35F);
|
||||
iceBeams.lineTo(0.25F, 0.15F);
|
||||
|
||||
iceBeams.moveTo(0.60F, 0.2F);
|
||||
iceBeams.lineTo(0.70F, 0F);
|
||||
|
||||
iceBeams.moveTo(0.9F, 0.25F);
|
||||
iceBeams.lineTo(1.0F, 0.05F);
|
||||
|
||||
iceOutline.moveTo(0F, 0.161F);
|
||||
iceOutline.lineTo(0.542F, 0F);
|
||||
iceOutline.lineTo(1.0F, 0.093F);
|
||||
iceOutline.lineTo(1.0F, 0.441F);
|
||||
iceOutline.lineTo(0.489F, 0.650F);
|
||||
iceOutline.lineTo(0.0F, 0.531F);
|
||||
iceOutline.closePath();
|
||||
|
||||
iceFaces[1] = new Path2D.Float();
|
||||
iceFaces[1].moveTo(0F, 0.161F);
|
||||
iceFaces[1].lineTo(0.542F, 0F);
|
||||
iceFaces[1].lineTo(1.0F, 0.093F);
|
||||
iceFaces[1].lineTo(0.489F, 0.263F);
|
||||
iceFaces[1].closePath();
|
||||
|
||||
iceFaces[2] = new Path2D.Float();
|
||||
iceFaces[2].moveTo(0.489F, 0.263F);
|
||||
iceFaces[2].lineTo(1.0F, 0.093F);
|
||||
iceFaces[2].lineTo(1.0F, 0.441F);
|
||||
iceFaces[2].lineTo(0.489F, 0.650F);
|
||||
iceFaces[2].closePath();
|
||||
|
||||
iceFaces[0] = new Path2D.Float();
|
||||
iceFaces[0].moveTo(0.0F, 0.161F);
|
||||
iceFaces[0].lineTo(0.489F, 0.263F);
|
||||
iceFaces[0].lineTo(0.489F, 0.650F);
|
||||
iceFaces[0].lineTo(0.0F, 0.531F);
|
||||
iceFaces[0].closePath();
|
||||
|
||||
iceShines[1] = new Path2D.Float();
|
||||
iceShines[1].moveTo(0.537F, 0.013F);
|
||||
iceShines[1].lineTo(0.930F, 0.099F);
|
||||
iceShines[1].lineTo(0.673F, 0.185F);
|
||||
iceShines[1].lineTo(0.556F, 0.187F);
|
||||
iceShines[1].lineTo(0.556F, 0.187F);
|
||||
iceShines[1].lineTo(0.742F, 0.086);
|
||||
iceShines[1].closePath();
|
||||
|
||||
iceShines[2] = new Path2D.Float();
|
||||
iceShines[2].moveTo(0.981F, 0.134F);
|
||||
iceShines[2].lineTo(0.981F, 0.423F);
|
||||
iceShines[2].lineTo(0.515F, 0.624F);
|
||||
iceShines[2].lineTo(0.571F, 0.557F);
|
||||
iceShines[2].lineTo(0.915F, 0.372F);
|
||||
iceShines[2].closePath();
|
||||
|
||||
iceShines[0] = new Path2D.Float();
|
||||
iceShines[0].moveTo(0.018F, 0.187F);
|
||||
iceShines[0].lineTo(0.205F, 0.229F);
|
||||
iceShines[0].lineTo(0.060F, 0.249F);
|
||||
iceShines[0].lineTo(0.044F, 0.475F);
|
||||
iceShines[0].lineTo(0.021F, 0.508F);
|
||||
iceShines[0].closePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawIcon(Graphics2D g2d, float scale, int animationStep) {
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.setStroke(new BasicStroke(2 / scale));
|
||||
g2d.draw(iceBeams);
|
||||
g2d.setStroke(new BasicStroke(4 / scale));
|
||||
g2d.translate(0F, 0.325F);
|
||||
g2d.draw(iceOutline);
|
||||
for(int i = 0; i < iceFaces.length; i++)
|
||||
{
|
||||
g2d.setColor(iceFaceColors[i]);
|
||||
g2d.fill(iceFaces[i]);
|
||||
g2d.setColor(iceShineAnimation[(i+animationStep) % iceShineAnimation.length]);
|
||||
g2d.fill(iceShines[i]);
|
||||
}
|
||||
g2d.translate(0F, -0.325F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnimated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.flaremicro.flaretv.visualforecast.icons.impl;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.Path2D;
|
||||
|
||||
import com.flaremicro.flaretv.visualforecast.icons.Icon;
|
||||
|
||||
public class SleetIcon extends Icon {
|
||||
|
||||
Path2D.Float iceOutline = new Path2D.Float();
|
||||
|
||||
Path2D.Float[] iceFaces = new Path2D.Float[3];
|
||||
Path2D.Float[] iceShines = new Path2D.Float[3];
|
||||
|
||||
Color[] iceFaceColors = new Color[] {
|
||||
new Color(0xfff8a0),
|
||||
new Color(0xfff14c),
|
||||
new Color(0xccbc00),
|
||||
};
|
||||
Color[] iceShineAnimation = new Color[] {
|
||||
new Color(0xFFFFFF),
|
||||
};
|
||||
|
||||
public SleetIcon(int id) {
|
||||
super(id);
|
||||
|
||||
iceOutline.moveTo(0F, 0.161F);
|
||||
iceOutline.lineTo(0.542F, 0F);
|
||||
iceOutline.lineTo(1.0F, 0.093F);
|
||||
iceOutline.lineTo(1.0F, 0.441F);
|
||||
iceOutline.lineTo(0.489F, 0.650F);
|
||||
iceOutline.lineTo(0.0F, 0.531F);
|
||||
iceOutline.closePath();
|
||||
|
||||
iceFaces[1] = new Path2D.Float();
|
||||
iceFaces[1].moveTo(0F, 0.161F);
|
||||
iceFaces[1].lineTo(0.542F, 0F);
|
||||
iceFaces[1].lineTo(1.0F, 0.093F);
|
||||
iceFaces[1].lineTo(0.489F, 0.263F);
|
||||
iceFaces[1].closePath();
|
||||
|
||||
iceFaces[2] = new Path2D.Float();
|
||||
iceFaces[2].moveTo(0.489F, 0.263F);
|
||||
iceFaces[2].lineTo(1.0F, 0.093F);
|
||||
iceFaces[2].lineTo(1.0F, 0.441F);
|
||||
iceFaces[2].lineTo(0.489F, 0.650F);
|
||||
iceFaces[2].closePath();
|
||||
|
||||
iceFaces[0] = new Path2D.Float();
|
||||
iceFaces[0].moveTo(0.0F, 0.161F);
|
||||
iceFaces[0].lineTo(0.489F, 0.263F);
|
||||
iceFaces[0].lineTo(0.489F, 0.650F);
|
||||
iceFaces[0].lineTo(0.0F, 0.531F);
|
||||
iceFaces[0].closePath();
|
||||
|
||||
iceShines[1] = new Path2D.Float();
|
||||
iceShines[1].moveTo(0.537F, 0.013F);
|
||||
iceShines[1].lineTo(0.930F, 0.099F);
|
||||
iceShines[1].lineTo(0.673F, 0.185F);
|
||||
iceShines[1].lineTo(0.556F, 0.187F);
|
||||
iceShines[1].lineTo(0.556F, 0.187F);
|
||||
iceShines[1].lineTo(0.742F, 0.086);
|
||||
iceShines[1].closePath();
|
||||
|
||||
iceShines[2] = new Path2D.Float();
|
||||
iceShines[2].moveTo(0.981F, 0.134F);
|
||||
iceShines[2].lineTo(0.981F, 0.423F);
|
||||
iceShines[2].lineTo(0.515F, 0.624F);
|
||||
iceShines[2].lineTo(0.571F, 0.557F);
|
||||
iceShines[2].lineTo(0.915F, 0.372F);
|
||||
iceShines[2].closePath();
|
||||
|
||||
iceShines[0] = new Path2D.Float();
|
||||
iceShines[0].moveTo(0.018F, 0.187F);
|
||||
iceShines[0].lineTo(0.205F, 0.229F);
|
||||
iceShines[0].lineTo(0.060F, 0.249F);
|
||||
iceShines[0].lineTo(0.044F, 0.475F);
|
||||
iceShines[0].lineTo(0.021F, 0.508F);
|
||||
iceShines[0].closePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawIcon(Graphics2D g2d, float scale, int animationStep) {
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.setStroke(new BasicStroke(4 / scale));
|
||||
g2d.translate(0F, 0.325F);
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.draw(iceOutline);
|
||||
for(int i = 0; i < iceFaces.length; i++)
|
||||
{
|
||||
g2d.setColor(iceFaceColors[i]);
|
||||
g2d.fill(iceFaces[i]);
|
||||
g2d.setColor(iceShineAnimation[(i+animationStep) % iceShineAnimation.length]);
|
||||
g2d.fill(iceShines[i]);
|
||||
}
|
||||
g2d.translate(0F, -0.325F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnimated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.flaremicro.flaretv.visualforecast.providerapi;
|
||||
|
||||
public abstract class ForecastProvider {
|
||||
ForecastProviderManager pluginManager;
|
||||
|
||||
protected final void setAsProvider(String authority)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public abstract void init();
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.flaremicro.flaretv.visualforecast.providerapi;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.flaremicro.util.Util;
|
||||
|
||||
public class ForecastProviderManager {
|
||||
public static final float API_VERSION = 0.0F;
|
||||
private Logger log = Util.getDefaultLogger();
|
||||
private ForecastProvider loadedProvider;
|
||||
|
||||
public void loadProviders(File file) {
|
||||
Util.getDefaultLogger().info("Loading provider " + file.getName());
|
||||
|
||||
try
|
||||
{
|
||||
URLClassLoader classLoader = new URLClassLoader(new URL[] { file.toURI().toURL() });
|
||||
Properties properties = new Properties();
|
||||
InputStream propStream = classLoader.getResourceAsStream("provider.inf");
|
||||
properties.load(propStream);
|
||||
Util.cleanClose(propStream);
|
||||
|
||||
String mainClassStr = properties.getProperty("main-class", "");
|
||||
Class<?> mainClass = classLoader.loadClass(mainClassStr);
|
||||
Object instance = mainClass.newInstance();
|
||||
if (instance instanceof ForecastProvider)
|
||||
{
|
||||
loadedProvider = (ForecastProvider) instance;
|
||||
loadedProvider.init();
|
||||
log.info("Provider " + file.getName() + " loaded!");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.info("Provider " + file.getName() + " main class is wrong object type");
|
||||
log.info("(Does main class not extend ForecastProvider?)");
|
||||
}
|
||||
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
log.info("Provider " + file.getName() + " main class not found:");
|
||||
e.printStackTrace();
|
||||
log.info("(Is the information file invalid?)");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
log.info("Provider " + file.getName() + " failed to read information file:");
|
||||
e.printStackTrace();
|
||||
log.info("(Is the information file defined?)");
|
||||
}
|
||||
catch (InstantiationException e)
|
||||
{
|
||||
log.info("Provider " + file.getName() + " failed to instantiate main class:");
|
||||
e.printStackTrace();
|
||||
log.info("(Does main class not implement empty constructor?)");
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
package com.flaremicro.flaretv.visualforecast.forecast;
|
||||
package com.flaremicro.flaretv.visualforecast.providerapi;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
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.icons.IconProvider;
|
||||
|
||||
public class MockForecastProvider {
|
||||
@@ -34,6 +38,11 @@ public class MockForecastProvider {
|
||||
new WeatherType(IconProvider.SCATTERD_THUNDERSTORMS.id, "Scattered","T'Storms", true),
|
||||
new WeatherType(IconProvider.SNOW.id, "Snow", true),
|
||||
new WeatherType(IconProvider.SUN.id, "Sun", false),
|
||||
new WeatherType(IconProvider.FOG.id, "Fog", false),
|
||||
new WeatherType(IconProvider.HAIL.id, "Hail", false),
|
||||
new WeatherType(IconProvider.BUTTER_RAIN.id, "Paula", "Dean", false),
|
||||
new WeatherType(IconProvider.BUTTER.id, "Unsalted", "Butter", false),
|
||||
//new WeatherType(IconProvider.INVALID_RAIN.id, "Your", "Mom", false),
|
||||
};
|
||||
|
||||
|
||||
@@ -57,34 +66,41 @@ public class MockForecastProvider {
|
||||
|
||||
private static DayForecast[] provideDayForecast(Random random)
|
||||
{
|
||||
DayForecast[] df = new DayForecast[7 + random.nextInt(2)];
|
||||
DayForecast[] df = new DayForecast[8];
|
||||
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)
|
||||
if(random.nextInt(11) == 10)
|
||||
{
|
||||
byte temp = hiTemp;
|
||||
hiTemp = loTemp;
|
||||
loTemp = temp;
|
||||
df[i] = new DayForecast(ValueCheck.NO_DATA_BYTE, ValueCheck.NO_DATA_BYTE, (byte)0, null, null, ValueCheck.NO_DATA_FLOAT);
|
||||
}
|
||||
|
||||
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)
|
||||
else
|
||||
{
|
||||
percipPercent = random.nextFloat() * 100;
|
||||
}
|
||||
byte hiTemp = (byte)(random.nextInt(60)-20);
|
||||
byte loTemp = (byte)(random.nextInt(60)-20);
|
||||
if(hiTemp < loTemp)
|
||||
{
|
||||
byte temp = hiTemp;
|
||||
hiTemp = loTemp;
|
||||
loTemp = temp;
|
||||
}
|
||||
|
||||
df[i] = new DayForecast(hiTemp, loTemp, iconId, weatherLine1, weatherLine2, percipPercent);
|
||||
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;
|
||||
}
|
||||
93
src/com/flaremicro/util/Util.java
Normal file
93
src/com/flaremicro/util/Util.java
Normal file
@@ -0,0 +1,93 @@
|
||||
package com.flaremicro.util;
|
||||
|
||||
import java.applet.Applet;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.flaremicro.util.logging.LogFormatter;
|
||||
import com.flaremicro.util.logging.LogOutputStream;
|
||||
|
||||
|
||||
public class Util {
|
||||
public static final long INSTANCE_ID = Math.abs(new Random().nextLong());
|
||||
public static final String LOGGER_NAME = "VisualForecast 1000 Logger";
|
||||
|
||||
static
|
||||
{
|
||||
initLogger();
|
||||
}
|
||||
|
||||
public static Logger getDefaultLogger() {
|
||||
return Logger.getLogger(LOGGER_NAME);
|
||||
}
|
||||
|
||||
public static void initLogger() {
|
||||
Logger log = getDefaultLogger();
|
||||
log.setUseParentHandlers(false);
|
||||
ConsoleHandler handler = new ConsoleHandler();
|
||||
handler.setFormatter(new LogFormatter());
|
||||
log.addHandler(handler);
|
||||
System.setErr(new PrintStream(new LogOutputStream(log, java.util.logging.Level.SEVERE)));
|
||||
System.setOut(new PrintStream(new LogOutputStream(log, java.util.logging.Level.INFO)));
|
||||
log.info("Initialized logger successfully");
|
||||
log.info("Using native Java logger, ID 0J3QvtGCINGD0YHQtdC70LXRgdGBINCbNNCI");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse arguments, in arg=value format, or just arg for arguments with no
|
||||
* value. Values can contain = signs, but not arguments.
|
||||
*
|
||||
* @param args
|
||||
* @param keyToLower
|
||||
* @return
|
||||
*/
|
||||
public static HashMap<String, String> parseArgs(String args[], boolean keyToLower) {
|
||||
HashMap<String, String> map = new HashMap<String, String>();
|
||||
for (String s : args)
|
||||
{
|
||||
String[] res = s.split("=", 2);
|
||||
if (keyToLower)
|
||||
res[0].toLowerCase();
|
||||
if (res.length > 1)
|
||||
{
|
||||
map.put(res[0], res[1]);
|
||||
}
|
||||
else map.put(res[0], "");
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static boolean cleanClose(Closeable closeable) {
|
||||
try
|
||||
{
|
||||
if (closeable != null)
|
||||
closeable.close();
|
||||
return true;
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static HashMap<String, String> toArguments(Applet applet, String[] expectedParameters) {
|
||||
HashMap<String, String> arguments = new HashMap<String, String>();
|
||||
if (applet == null || expectedParameters == null)
|
||||
return arguments;
|
||||
for (String parameter : expectedParameters)
|
||||
{
|
||||
String value = applet.getParameter(parameter);
|
||||
if (value != null)
|
||||
{
|
||||
arguments.put(parameter, value);
|
||||
}
|
||||
}
|
||||
return arguments;
|
||||
}
|
||||
}
|
||||
31
src/com/flaremicro/util/logging/LogFormatter.java
Normal file
31
src/com/flaremicro/util/logging/LogFormatter.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.flaremicro.util.logging;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
|
||||
public class LogFormatter extends Formatter {
|
||||
String sep = System.getProperty("line.separator");
|
||||
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
@Override
|
||||
public String format(LogRecord record) {
|
||||
String fmessage = "";
|
||||
if(record.getLevel() == Level.SEVERE)
|
||||
fmessage += "["+format.format(System.currentTimeMillis())+"][SEVERE]";
|
||||
else if(record.getLevel() == Level.WARNING)
|
||||
fmessage += "["+format.format(System.currentTimeMillis())+"][WARNING]";
|
||||
else if(record.getLevel() == Level.INFO)
|
||||
fmessage += "["+format.format(System.currentTimeMillis())+"][INFO]";
|
||||
return fmessage += this.formatMessage(record) + sep;
|
||||
}
|
||||
public String getHead(Handler h) {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getTail(Handler h) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
38
src/com/flaremicro/util/logging/LogOutputStream.java
Normal file
38
src/com/flaremicro/util/logging/LogOutputStream.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package com.flaremicro.util.logging;
|
||||
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class LogOutputStream extends OutputStream {
|
||||
|
||||
String buffer = "";
|
||||
Logger logger;
|
||||
Level level;
|
||||
|
||||
public LogOutputStream(Logger logger, Level level)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
buffer += (char)((byte)b);
|
||||
if(buffer.endsWith("\n") || buffer.endsWith("\r\n"))
|
||||
{
|
||||
buffer = buffer.replace("\r", "").replace("\n", "");
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
public void flush()
|
||||
{
|
||||
logger.log(level, buffer);
|
||||
buffer = "";
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user