1 Commits

Author SHA1 Message Date
Flare Microsystems
81d81bebae No idea what this changed 2024-03-07 19:30:15 -08:00
10 changed files with 162 additions and 479 deletions

View File

@@ -1,4 +1,4 @@
#VisualForecast 1000 Properties file. Functional provider must be set for successful boot!
#Thu Mar 07 16:27:03 PST 2024
#Thu Mar 07 19:30:06 PST 2024
towns-by-code=
towns-by-name-and-province=Vancouver,BC;Kamloops,BC;Kelowna,BC

View File

@@ -9,34 +9,10 @@ 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

View File

@@ -1,31 +0,0 @@
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 "";
}
}

View File

@@ -1,38 +0,0 @@
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 = "";
}
}

View File

@@ -41,7 +41,7 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
*/
private static final long serialVersionUID = 1L;
private VolatileImage frameBuffer = null;
private BufferedImage frameBuffer = null;
private Font font = null;
@@ -52,7 +52,6 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
private Rectangle redrawBound = new Rectangle(0, 0, 1, 1);
private Rectangle exclusiveRedrawBound = null;
private Rectangle crawlBound = null;
private String currentTown = "";
private String currentForecast = "";
@@ -60,29 +59,22 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
private ForecastProvider forecastProvider = null;
private PropertyManager propManager;
private String[] crawlStrings = new String[0];
String currentCrawlString = null;
private int crawlPosition = 0;
private int stringIndex = -1;
private int currentCrawlStringWidth = 0;
public Rectangle nextRedrawBound = null;
public RenderPanel(PropertyManager propManager) {
loadCrawlStrings();
//loadCrawlStrings();
this.addComponentListener(this);
this.setDoubleBuffered(true);
this.propManager = propManager;
font = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf"));
currentFlavour.initDisplay(this, null, ticks, iconAnimationTicks);
//new Thread(new TickThread(this, 30)).start();
}
private Graphics2D prepareFrameBuffer() {
GraphicsConfiguration gc = this.getGraphicsConfiguration();
if (frameBuffer == null || frameBuffer.validate(gc) == VolatileImage.IMAGE_INCOMPATIBLE)
private Graphics2D getBuffer() {
if (frameBuffer == null)
{
System.out.println("new image req'd");
frameBuffer = gc.createCompatibleVolatileImage(W, H);
frameBuffer = this.getGraphicsConfiguration().createCompatibleImage(W, H);
}
return (Graphics2D) frameBuffer.getGraphics();
}
@@ -108,76 +100,67 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = prepareFrameBuffer();
if(g.getClipBounds().equals(this.crawlBound))
if(frameBuffer == null)
{
g2d.setColor(BG_BLUE);
g2d.fillRect(0, H - INFOBAR_HEIGHT, W, INFOBAR_HEIGHT);
g2d.setColor(Color.DARK_GRAY);
g2d.drawLine(0, H - INFOBAR_HEIGHT + STROKE_OFFSET, W, H - INFOBAR_HEIGHT + STROKE_OFFSET);
g2d.setColor(Color.WHITE);
g2d.drawLine(0, H - INFOBAR_HEIGHT + STROKE_WIDTH + STROKE_OFFSET, W, H - INFOBAR_HEIGHT + STROKE_WIDTH + STROKE_OFFSET);
if (this.currentCrawlString != null)
{
g2d.setFont(font.deriveFont(26F));
DrawingUtil.drawOutlinedString(g2d, this.crawlPosition, H - INFOBAR_HEIGHT + 30, this.currentCrawlString, Color.WHITE, Color.BLACK, 2);
}
g2d.dispose();
g.drawImage(frameBuffer, 0, 0, getWidth(), getHeight(), this);
return;
initBuffer();
}
drawMainRegion(g2d);
if (currentFlavour != null)
{
if (this.getBounds().equals(g.getClipBounds()))
this.currentFlavour.drawDisplay(this, g2d, ticks, iconAnimationTicks);
if (g.getClipBounds() != null)
this.currentFlavour.drawBoundLimitedDisplay(this, g2d, g.getClipBounds(), ticks, iconAnimationTicks);
}
g2d.dispose();
g.drawImage(frameBuffer, 0, 0, getWidth(), getHeight(), this);
}
public void initBuffer() {
Graphics2D g2d = getBuffer();
this.drawEntireMainRegion(g2d);
g2d.dispose();
}
private void drawMainRegion(Graphics2D g2d) {
private void drawTitleHeader(Graphics2D g2d)
{
g2d.setFont(font.deriveFont(24F));
g2d.setStroke(new BasicStroke(2));
g2d.setColor(BG_PURPLE);
g2d.fillRect(0, 0, W, TOPBAR_HEIGHT);
g2d.setPaint(new GradientPaint(0, HEADERBAR_Y, BG_OORANGE, 0, HEADERBAR_Y + (HEADERBAR_HEIGHT + 10), BG_PURPLE));
g2d.shear(HEADERBAR_SHEAR, 0);
g2d.fillRect(-HEADERBAR_OFFSET, HEADERBAR_Y, HEADERBAR_WIDTH, HEADERBAR_HEIGHT);
g2d.shear(-HEADERBAR_SHEAR, 0);
DrawingUtil.drawOutlinedString(g2d, 60, HEADERBAR_Y + 18, currentForecast, Color.WHITE, Color.BLACK, 2);
g2d.setFont(font.deriveFont(36F));
DrawingUtil.drawOutlinedString(g2d, 60, HEADERBAR_Y + 52, currentTown, Color.YELLOW, Color.BLACK, 2);
}
private void drawTimeHeader(Graphics2D g2d)
{
g2d.setFont(font.deriveFont(24F));
g2d.setPaint(new GradientPaint(0, HEADERBAR_Y, BG_PURPLE.brighter().brighter().brighter(), 0, HEADERBAR_Y + (HEADERBAR_HEIGHT + 10), BG_PURPLE));
g2d.shear(HEADERBAR_SHEAR, 0);
g2d.fillRect(W - TIMEBAR_WIDTH + TIMEBAR_OFFSET, TIMEBAR_Y, TIMEBAR_WIDTH, TIMEBAR_HEIGHT);
g2d.shear(-HEADERBAR_SHEAR, 0);
g2d.setPaint(new GradientPaint(0, TOPBAR_HEIGHT, BG_PURPLE, 0, MAINBAR_HEIGHT, BG_OORANGE));
g2d.fillRect(0, TOPBAR_HEIGHT, W, MAINBAR_HEIGHT);
g2d.fillRect(0, TOPBAR_HEIGHT, W, MAINBAR_HEIGHT);
// g2d.setColor(Color.GRAY);
// g2d.drawRect(60, TOPBAR_HEIGHT+2, W-120, MAINBAR_HEIGHT-4);
String dateString = DATE_FORMAT.format(System.currentTimeMillis()) + getDayOfMonthSuffix();
String timeString = TIME_FORMAT.format(System.currentTimeMillis());
DrawingUtil.drawOutlinedString(g2d, 60, HEADERBAR_Y + 18, currentForecast, Color.WHITE, Color.BLACK, 2);
int sw = g2d.getFontMetrics().stringWidth(dateString);
DrawingUtil.drawOutlinedString(g2d, W - sw - 60, TIMEBAR_Y + 18, dateString, Color.WHITE, Color.BLACK, 2);
sw = g2d.getFontMetrics().stringWidth(timeString);
DrawingUtil.drawOutlinedString(g2d, W - sw - 60, TIMEBAR_Y + 36, timeString, Color.WHITE, Color.BLACK, 2);
g2d.setFont(font.deriveFont(36F));
DrawingUtil.drawOutlinedString(g2d, 60, HEADERBAR_Y + 52, currentTown, Color.YELLOW, Color.BLACK, 2);
}
private void drawHeader(Graphics2D g2d)
{
g2d.setColor(BG_PURPLE);
g2d.fillRect(0, 0, W, TOPBAR_HEIGHT);
drawTitleHeader(g2d);
drawTimeHeader(g2d);
}
public void drawMainGradient(Graphics2D g2d)
{
g2d.setPaint(new GradientPaint(0, TOPBAR_HEIGHT, BG_PURPLE, 0, MAINBAR_HEIGHT, BG_OORANGE));
g2d.fillRect(0, TOPBAR_HEIGHT, W, MAINBAR_HEIGHT);
}
private void drawCrawlBar(Graphics2D g2d){
g2d.setStroke(new BasicStroke(2));
g2d.setColor(BG_BLUE);
g2d.fillRect(0, H - INFOBAR_HEIGHT, W, INFOBAR_HEIGHT);
@@ -186,12 +169,17 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
g2d.setColor(Color.WHITE);
g2d.drawLine(0, H - INFOBAR_HEIGHT + STROKE_WIDTH + STROKE_OFFSET, W, H - INFOBAR_HEIGHT + STROKE_WIDTH + STROKE_OFFSET);
if (this.currentCrawlString != null)
/*if (this.currentCrawlString != null)
{
g2d.setFont(font.deriveFont(26F));
DrawingUtil.drawOutlinedString(g2d, this.crawlPosition, H - INFOBAR_HEIGHT + 30, this.currentCrawlString, Color.WHITE, Color.BLACK, 2);
}
}*/
}
private void drawEntireMainRegion(Graphics2D g2d) {
drawHeader(g2d);
drawMainGradient(g2d);
drawCrawlBar(g2d);
}
public void tick() {
@@ -202,31 +190,28 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
//Clock and icon animations, should use repaint regions later
if (getWidth() > 0 && getHeight() > 0)
{
repaint(this.redrawBound);
Graphics2D g2d = this.getBuffer();
this.drawTimeHeader(g2d);
g2d.dispose();
requestBoundedRepaint();
//repaint(this.redrawBound);
}
}
if (this.currentFlavour != null)
{
this.currentFlavour.tick(this, ticks, iconAnimationTicks);
}
if (this.crawlStrings != null && this.crawlStrings.length > 0 && this.crawlPosition + this.currentCrawlStringWidth <= 0)
if(this.nextRedrawBound != null)
{
stringIndex = ((stringIndex + 1) % this.crawlStrings.length);
this.currentCrawlString = this.crawlStrings[stringIndex];
this.crawlPosition = W;
Graphics g = this.getGraphics();
this.currentCrawlStringWidth = g.getFontMetrics(font.deriveFont(26F)).stringWidth(currentCrawlString);
g.dispose();
Graphics2D g2d = this.getBuffer();
if(nextRedrawBound.equals(this.getBounds()))
{
this.currentFlavour.drawDisplay(this, g2d, ticks, iconAnimationTicks);
}
this.currentFlavour.drawBoundLimitedDisplay(this, g2d, nextRedrawBound, ticks, iconAnimationTicks);
g2d.dispose();
repaint(nextRedrawBound);
}
else if (this.currentCrawlString != null)
{
this.crawlPosition-=2;
repaint(0, this.crawlBound.x, this.crawlBound.y, this.crawlBound.width, this.crawlBound.height);
}
}
public BufferedImage getSnapshot() {
return frameBuffer.getSnapshot();
}
private void addRedrawBound(int x, int y, int w, int h, boolean isExclusive) {
@@ -253,10 +238,6 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
public void loseRedrawRegion() {
this.redrawBound = null;
addRedrawBound(W - TIMEBAR_WIDTH + TIMEBAR_OFFSET, TIMEBAR_Y, TIMEBAR_WIDTH, TIMEBAR_HEIGHT, false);
float wScale = getWidth() / (float) W;
float hScale = getHeight() / (float) H;
this.crawlBound = new Rectangle((int) 0, (int) ((H - INFOBAR_HEIGHT + 8) * hScale), (int) (W * wScale), (int) (30 * hScale));
if (this.currentFlavour != null)
this.currentFlavour.redrawRegionlost(this);
}
@@ -295,6 +276,7 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
public void nextDisplay() {
this.currentFlavour = new DayForecastDisplay();
this.currentFlavour.initDisplay(this, forecastProvider, ticks, iconAnimationTicks);
initBuffer();
this.loseRedrawRegion();
this.requestFullRepaint();
}
@@ -308,18 +290,25 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
}
public void requestFullRepaint() {
repaint();
this.nextRedrawBound = this.getBounds();
}
public void requestBoundedRepaint() {
repaint(redrawBound);
if(nextRedrawBound == null)
nextRedrawBound = redrawBound;
else
nextRedrawBound.add(redrawBound);
}
public void requestExclusiveBoundedRepaint() {
repaint(exclusiveRedrawBound);
if(nextRedrawBound == null)
nextRedrawBound = exclusiveRedrawBound;
else
nextRedrawBound.add(exclusiveRedrawBound);
//repaint(exclusiveRedrawBound);
}
private void loadCrawlStrings() {
/*private void loadCrawlStrings() {
File crawl = new File("./crawl.txt");
ArrayList<String> strings = new ArrayList<String>();
if (crawl != null)
@@ -344,7 +333,7 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
}
}
this.crawlStrings = strings.toArray(new String[strings.size()]);
}
}*/
/*@Override
public void run() {

View File

@@ -0,0 +1,57 @@
package com.flaremicro.visualforecast;
/**
* TImer class, deals with ticks, game speedup, and slowdown
* @author Vulpovile
*
*/
public class Timer {
private final int ticksPerSecond;
private long lastTickTime = 0;
private long currentTime = 0;
private long ticksPassed = 0;
/**
* Creates a timer with a set amount ticks per second
* @param ticksPerSecond
*/
public Timer(int ticksPerSecond)
{
this.ticksPerSecond = 1000/ticksPerSecond;
currentTime = System.currentTimeMillis();
lastTickTime = currentTime;
}
/**
* Resets the timer, prevents the superspeed bug when loading or generating levels
*/
public void reset()
{
currentTime = System.currentTimeMillis();
lastTickTime = currentTime;
}
/**
* Ticks the timer and returns how many ticks were missed by the game (to catch up with bad framerates)
* @return ticks passed
*/
public long tick()
{
if(ticksPassed > 0) ticksPassed--;
currentTime = System.currentTimeMillis();
if(lastTickTime < currentTime-ticksPerSecond)
{
ticksPassed = (currentTime-lastTickTime)/ticksPerSecond;
lastTickTime = currentTime - (currentTime-lastTickTime)%ticksPerSecond;
}
if(ticksPassed > 200L)
{
System.out.println("Time moving too fast! Did the system time change or is the game overloaded?");
System.out.println("Moving time forward " + ticksPassed + " ticks");
ticksPassed = 0;
}
else if(ticksPassed < 0L)
{
System.out.println("Time moved backwards! Did the system time change?");
System.out.println("Moving time backwards " + -ticksPassed + " ticks");
ticksPassed = 0;
}
return ticksPassed;
}
}

View File

@@ -6,14 +6,12 @@ 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;
import com.flaremicro.visualforecast.RenderPanel;
public class ForecastProviderManager {
public static final float API_VERSION = 0.0F;
private Logger log = Util.getDefaultLogger();
private ForecastProvider loadedProvider;
private String loadedProviderName;
private RenderPanel mainPanel;
@@ -29,7 +27,7 @@ public class ForecastProviderManager {
}
public ForecastProvider loadProvider(File file) {
Util.getDefaultLogger().info("Loading provider " + file.getName());
//Util.getDefaultLogger().info("Loading provider " + file.getName());
try
{
URLClassLoader classLoader = new URLClassLoader(new URL[] { file.toURI().toURL() });
@@ -49,53 +47,53 @@ public class ForecastProviderManager {
loadedProvider.forecastProviderManager = this;
loadedProviderName = file.getName().substring(0, file.getName().length() - 4);
loadedProvider.init();
log.info("Provider " + file.getName() + " loaded! (Name set to " + loadedProviderName +")");
//log.info("Provider " + file.getName() + " loaded! (Name set to " + loadedProviderName +")");
return loadedProvider;
}
else
{
log.info("Provider " + file.getName() + " main class is wrong object type");
log.info("(Does main class not extend ForecastProvider?)");
//log.info("Provider " + file.getName() + " main class is wrong object type");
//log.info("(Does main class not extend ForecastProvider?)");
}
}
else
{
log.info("Provider " + file.getName() + " properties file was not found");
log.info("(Is the jar path correct?)");
//log.info("Provider " + file.getName() + " properties file was not found");
//log.info("(Is the jar path correct?)");
}
}
catch (ClassNotFoundException e)
{
log.info("Provider " + file.getName() + " main class not found:");
//log.info("Provider " + file.getName() + " main class not found:");
e.printStackTrace();
log.info("(Is the information file invalid?)");
//log.info("(Is the information file invalid?)");
}
catch (IOException e)
{
log.info("Provider " + file.getName() + " failed to read information file:");
//log.info("Provider " + file.getName() + " failed to read information file:");
e.printStackTrace();
log.info("(Is the information file defined?)");
//log.info("(Is the information file defined?)");
}
catch (InstantiationException e)
{
log.info("Provider " + file.getName() + " failed to instantiate main class:");
//log.info("Provider " + file.getName() + " failed to instantiate main class:");
e.printStackTrace();
log.info("(Does main class not implement empty constructor?)");
//log.info("(Does main class not implement empty constructor?)");
}
catch (IllegalAccessException e)
{
log.info("Provider " + file.getName() + " failed to instantiate main class:");
//log.info("Provider " + file.getName() + " failed to instantiate main class:");
e.printStackTrace();
log.info("(Does the program have reflection permission?)");
//log.info("(Does the program have reflection permission?)");
}
catch (Exception e)
{
log.info("Provider " + file.getName() + " failed while loading:");
//log.info("Provider " + file.getName() + " failed while loading:");
e.printStackTrace();
}
catch (Throwable e)
{
log.info("Provider " + file.getName() + " failed catastrophically while loading:");
//log.info("Provider " + file.getName() + " failed catastrophically while loading:");
e.printStackTrace();
}
return null;

View File

@@ -133,6 +133,7 @@ public class DayForecastDisplay implements Display {
@Override
public void drawDisplay(RenderPanel renderer, Graphics2D g2d, long ticks, int iconTicks) {
g2d.setStroke(new BasicStroke(2));
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));
@@ -175,11 +176,6 @@ public class DayForecastDisplay implements Display {
}
}
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) {
@@ -246,15 +242,17 @@ public class DayForecastDisplay implements Display {
@Override
public void drawBoundLimitedDisplay(RenderPanel renderer, Graphics2D g2d, Rectangle bounds, long ticks, int iconTicks) {
g2d.setStroke(new BasicStroke(2));
if (details != null && currentTown != null && currentTown.getDayForecast() != null && currentTown.getDayForecast().length > 0)
{
if (animationTicks < 0)
{
g2d.drawImage(mainBound, RenderConstants.SIDE_OFFSET - 1, RenderConstants.TOPBAR_HEIGHT + 14, renderer);
drawIcons(g2d, currentTown, dayOffset, iconTicks);
}
else
{
g2d.setClip(animationTicks, RenderConstants.TOPBAR_HEIGHT + 14, RenderConstants.SIDE_OFFSET, MAINBAR_HEIGHT - 28);
renderer.drawMainGradient(g2d);
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)

View File

@@ -1,266 +0,0 @@
package com.flaremicro.visualforecast.displays;
import static com.flaremicro.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.visualforecast.RenderPanel;
import com.flaremicro.visualforecast.api.ForecastProvider;
import com.flaremicro.visualforecast.forecast.DayForecast;
import com.flaremicro.visualforecast.forecast.ForecastDetails;
import com.flaremicro.visualforecast.forecast.TownForecast;
import com.flaremicro.visualforecast.forecast.ValueCheck;
import com.flaremicro.visualforecast.graphics.DrawingUtil;
import com.flaremicro.visualforecast.graphics.FontManager;
import com.flaremicro.visualforecast.graphics.RenderConstants;
import com.flaremicro.visualforecast.icons.IconProvider;
public class DayForecastDisplayOldAnimation implements Display {
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 DayForecastDisplayOldAnimation() {
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.nextDisplay();
}
else
{
previousTown = currentTown;
currentTown = details.getTownForecast()[townIndex];
renderer.setCurrentTown(currentTown.getTownName());
}
}
renderer.loseRedrawRegion();
renderer.requestFullRepaint();
}
}
}
@Override
public void initDisplay(RenderPanel renderer, ForecastProvider forecastProvider, long ticks, int iconTicks) {
this.details = forecastProvider != null ? forecastProvider.getForecast() : null;
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 drawDisplay(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 drawBoundLimitedDisplay(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);
}
@Override
public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) {
}
}

View File

@@ -1,3 +1,3 @@
#VisualForecast 1000 Properties file. Functional provider must be set for successful boot!
#Thu Mar 07 16:27:03 PST 2024
#Thu Mar 07 19:30:06 PST 2024
forecast-provider-jar=CanadaDatamartProvider.jar