Feature/hourlyforecast #4
Binary file not shown.
@@ -1,4 +1,4 @@
|
|||||||
#VisualForecast 1000 Properties file. Functional provider must be set for successful boot!
|
#VisualForecast 1000 Properties file. Functional provider must be set for successful boot!
|
||||||
#Fri Mar 08 16:38:56 PST 2024
|
#Fri Mar 15 19:46:22 PDT 2024
|
||||||
towns-by-code=
|
towns-by-code=
|
||||||
towns-by-name-and-province=Duncan,BC;Halifax,NS;Courtenay,BC;Comox,BC
|
towns-by-name-and-province=Vancouver,BC;Victora,BC;Kelowna,BC;Nanaimo,BC;Squamish,BC;Prince George,BC;Prince Rupert,BC
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import java.awt.image.BufferedImage;
|
|||||||
import java.awt.image.VolatileImage;
|
import java.awt.image.VolatileImage;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -29,7 +28,9 @@ import com.flaremicro.visualforecast.api.ForecastProvider;
|
|||||||
import com.flaremicro.visualforecast.displays.BootupDisplay;
|
import com.flaremicro.visualforecast.displays.BootupDisplay;
|
||||||
import com.flaremicro.visualforecast.displays.DayForecastDisplay;
|
import com.flaremicro.visualforecast.displays.DayForecastDisplay;
|
||||||
import com.flaremicro.visualforecast.displays.Display;
|
import com.flaremicro.visualforecast.displays.Display;
|
||||||
|
import com.flaremicro.visualforecast.displays.DisplayFactory;
|
||||||
import com.flaremicro.visualforecast.displays.HourlyForecastDisplay;
|
import com.flaremicro.visualforecast.displays.HourlyForecastDisplay;
|
||||||
|
import com.flaremicro.visualforecast.displays.ThirtySixHourDisplay;
|
||||||
import com.flaremicro.visualforecast.forecast.ForecastDetails;
|
import com.flaremicro.visualforecast.forecast.ForecastDetails;
|
||||||
import com.flaremicro.visualforecast.graphics.DrawingUtil;
|
import com.flaremicro.visualforecast.graphics.DrawingUtil;
|
||||||
import com.flaremicro.visualforecast.graphics.FontManager;
|
import com.flaremicro.visualforecast.graphics.FontManager;
|
||||||
@@ -70,6 +71,8 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
|
|||||||
private int stringIndex = -1;
|
private int stringIndex = -1;
|
||||||
private int currentCrawlStringWidth = 0;
|
private int currentCrawlStringWidth = 0;
|
||||||
|
|
||||||
|
DisplayFactory displayFactory;
|
||||||
|
|
||||||
public RenderPanel(PropertyManager propManager) {
|
public RenderPanel(PropertyManager propManager) {
|
||||||
loadCrawlStrings();
|
loadCrawlStrings();
|
||||||
this.addComponentListener(this);
|
this.addComponentListener(this);
|
||||||
@@ -77,6 +80,7 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
|
|||||||
this.propManager = propManager;
|
this.propManager = propManager;
|
||||||
font = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf"));
|
font = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf"));
|
||||||
currentFlavour.initDisplay(this, null, ticks, iconAnimationTicks);
|
currentFlavour.initDisplay(this, null, ticks, iconAnimationTicks);
|
||||||
|
displayFactory = new DisplayFactory(propManager);
|
||||||
//new Thread(new TickThread(this, 30)).start();
|
//new Thread(new TickThread(this, 30)).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,7 +305,13 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void nextDisplay() {
|
public void nextDisplay() {
|
||||||
|
/*if(this.currentFlavour instanceof DayForecastDisplay)
|
||||||
this.currentFlavour = new HourlyForecastDisplay();
|
this.currentFlavour = new HourlyForecastDisplay();
|
||||||
|
else
|
||||||
|
this.currentFlavour = new DayForecastDisplay();*/
|
||||||
|
this.currentFlavour = displayFactory.nextDisplay();
|
||||||
|
/*this.currentFlavour = new ThirtySixHourDisplay();
|
||||||
|
*/
|
||||||
this.currentFlavour.initDisplay(this, forecastProvider, ticks, iconAnimationTicks);
|
this.currentFlavour.initDisplay(this, forecastProvider, ticks, iconAnimationTicks);
|
||||||
this.loseRedrawRegion();
|
this.loseRedrawRegion();
|
||||||
this.requestFullRepaint();
|
this.requestFullRepaint();
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package com.flaremicro.visualforecast;
|
package com.flaremicro.visualforecast;
|
||||||
|
|
||||||
import java.awt.BorderLayout;
|
|
||||||
import java.awt.EventQueue;
|
import java.awt.EventQueue;
|
||||||
|
import java.awt.GraphicsDevice;
|
||||||
|
import java.awt.GraphicsEnvironment;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
@@ -9,10 +10,13 @@ import java.awt.event.KeyListener;
|
|||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
import java.awt.event.WindowListener;
|
import java.awt.event.WindowListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.Timer;
|
import javax.swing.Timer;
|
||||||
|
|
||||||
|
import com.flaremicro.util.Util;
|
||||||
import com.flaremicro.visualforecast.api.ForecastProvider;
|
import com.flaremicro.visualforecast.api.ForecastProvider;
|
||||||
import com.flaremicro.visualforecast.api.ForecastProviderManager;
|
import com.flaremicro.visualforecast.api.ForecastProviderManager;
|
||||||
|
|
||||||
@@ -34,6 +38,7 @@ public class VisualForecastFrame extends JFrame implements WindowListener, KeyLi
|
|||||||
* Launch the application.
|
* Launch the application.
|
||||||
*/
|
*/
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
final Map<String, String> arguments = Util.parseArgs(args, true);
|
||||||
EventQueue.invokeLater(new Runnable() {
|
EventQueue.invokeLater(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try
|
try
|
||||||
@@ -41,6 +46,29 @@ public class VisualForecastFrame extends JFrame implements WindowListener, KeyLi
|
|||||||
VisualForecastFrame frame = new VisualForecastFrame();
|
VisualForecastFrame frame = new VisualForecastFrame();
|
||||||
frame.setVisible(true);
|
frame.setVisible(true);
|
||||||
frame.init();
|
frame.init();
|
||||||
|
|
||||||
|
if (arguments.containsKey("fullscreen"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
int index = Integer.parseInt(arguments.get("fullscreen"));
|
||||||
|
|
||||||
|
GraphicsDevice[] devices = GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices();
|
||||||
|
if(index < 0 || devices.length < index)
|
||||||
|
{
|
||||||
|
JOptionPane.showMessageDialog(frame, arguments.get("fullscreen") + " does not exist as a screen index");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
devices[index].setFullScreenWindow(frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NumberFormatException ex)
|
||||||
|
{
|
||||||
|
JOptionPane.showMessageDialog(frame, arguments.get("fullscreen") + " is not a valid screen index");
|
||||||
|
}
|
||||||
|
}
|
||||||
//GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[1].setFullScreenWindow(frame);
|
//GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[1].setFullScreenWindow(frame);
|
||||||
//frame.createBufferStrategy(2);
|
//frame.createBufferStrategy(2);
|
||||||
}
|
}
|
||||||
@@ -75,7 +103,6 @@ public class VisualForecastFrame extends JFrame implements WindowListener, KeyLi
|
|||||||
});
|
});
|
||||||
timer.start();
|
timer.start();
|
||||||
|
|
||||||
|
|
||||||
new Thread() {
|
new Thread() {
|
||||||
public void run() {
|
public void run() {
|
||||||
forecastProviderManager = new ForecastProviderManager(renderPane);
|
forecastProviderManager = new ForecastProviderManager(renderPane);
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package com.flaremicro.visualforecast.displays;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.flaremicro.visualforecast.RenderPanel;
|
||||||
|
import com.flaremicro.visualforecast.api.ForecastProvider;
|
||||||
|
import com.flaremicro.visualforecast.graphics.DrawingUtil;
|
||||||
|
import com.flaremicro.visualforecast.graphics.FontManager;
|
||||||
|
|
||||||
|
import static com.flaremicro.visualforecast.graphics.RenderConstants.*;
|
||||||
|
|
||||||
|
public class CurrentForecastDisplay implements Display {
|
||||||
|
|
||||||
|
private String[] lines = new String[0];
|
||||||
|
private Font font;
|
||||||
|
|
||||||
|
private int stringOffset = 0;
|
||||||
|
private int ticksBeforeChange = 0;
|
||||||
|
|
||||||
|
public CurrentForecastDisplay() {
|
||||||
|
font = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf")).deriveFont(30F);
|
||||||
|
|
||||||
|
/*
|
||||||
|
int w2 = g2d.getFontMetrics().stringWidth("EXTREME WEATHER ADVISORY");
|
||||||
|
drawOutlinedString(g2d, (W >> 1) - (w2 >> 1), TOPBAR_HEIGHT + 48, "EXTREME WEATHER ADVISORY", Color.RED, Color.BLACK, 2);
|
||||||
|
|
||||||
|
g2d.setFont(font.deriveFont(30F));
|
||||||
|
for (int i = 0; i < testString.length; i++)
|
||||||
|
{
|
||||||
|
drawOutlinedString(g2d, 90, TOPBAR_HEIGHT + 78 + 25 * i, testString[i], Color.WHITE, Color.BLACK, 1);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(RenderPanel renderer, long ticks, int iconTicks) {
|
||||||
|
ticksBeforeChange--;
|
||||||
|
if (ticksBeforeChange <= 0)
|
||||||
|
{
|
||||||
|
stringOffset += 9;
|
||||||
|
if (stringOffset < lines.length)
|
||||||
|
{
|
||||||
|
ticksBeforeChange = 200;
|
||||||
|
renderer.requestExclusiveBoundedRepaint();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
renderer.nextDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initDisplay(RenderPanel renderer, ForecastProvider forecastProvider, long ticks, int iconTicks) {
|
||||||
|
ticksBeforeChange = 200;
|
||||||
|
stringOffset = 0;
|
||||||
|
String test = "*IMPORTANT NOTICE*\n*THIS BETA IS UNFINISHED*\n\nThis is a Beta version of the VisualForeast 1000! Many things are not finished, and only the hourly and 7 day forecasts are ready. There will be a lot more to come!\nPlease note that there are some issues with data collection from Environment Canada resulting in missing or potentially incorrect information around midnight hours. This will be fixed as the project continues and the disclaimer will be removed.";
|
||||||
|
ArrayList<String> linesList = new ArrayList<String>();
|
||||||
|
|
||||||
|
renderer.setCurrentForecast("Welcome to the");
|
||||||
|
renderer.setCurrentTown("VisualForecast 1000");
|
||||||
|
|
||||||
|
BufferedImage disposableImage = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY);
|
||||||
|
Graphics2D g = disposableImage.createGraphics();
|
||||||
|
FontMetrics f = g.getFontMetrics(font);
|
||||||
|
String[] lines = test.split("\n");
|
||||||
|
for (int i = 0; i < lines.length; i++)
|
||||||
|
{
|
||||||
|
splitText(lines[i], W - 150 - STROKE_WIDTH, f, linesList);
|
||||||
|
//if(words[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
g.dispose();
|
||||||
|
disposableImage.flush();
|
||||||
|
|
||||||
|
redrawRegionlost(renderer);
|
||||||
|
|
||||||
|
this.lines = linesList.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void splitText(String text, int maxWidth, FontMetrics fontMetrics, ArrayList<String> lineList) {
|
||||||
|
|
||||||
|
text = text.trim();
|
||||||
|
//this.text.add(text);
|
||||||
|
if (fontMetrics.stringWidth(text) <= maxWidth)
|
||||||
|
lineList.add(text);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (text.length() > 0)
|
||||||
|
{
|
||||||
|
int idx = binSearch(text, fontMetrics, maxWidth, 1, text.length());
|
||||||
|
if (idx <= 0)
|
||||||
|
break;
|
||||||
|
String texPart = text.substring(0, idx).trim();
|
||||||
|
if (fontMetrics.stringWidth(text.substring(0, Math.min(text.length(), idx + 1))) > maxWidth && texPart.contains(" "))
|
||||||
|
{
|
||||||
|
idx = texPart.lastIndexOf(" ");
|
||||||
|
texPart = texPart.substring(0, idx);
|
||||||
|
}
|
||||||
|
lineList.add(texPart);
|
||||||
|
text = text.substring(idx).trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int binSearch(String string, FontMetrics fontMetrics, int key, int low, int high) {
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
while (low <= high)
|
||||||
|
{
|
||||||
|
int mid = low + ((high - low) / 2);
|
||||||
|
int midmetric = fontMetrics.stringWidth(string.substring(0, mid));
|
||||||
|
if (midmetric < key)
|
||||||
|
{
|
||||||
|
low = mid + 1;
|
||||||
|
index = mid;
|
||||||
|
}
|
||||||
|
else if (midmetric > key)
|
||||||
|
{
|
||||||
|
high = mid - 1;
|
||||||
|
}
|
||||||
|
else if (midmetric == key)
|
||||||
|
{
|
||||||
|
index = mid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawDisplay(RenderPanel renderer, Graphics2D g2d, long ticks, int iconTicks) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawBoundLimitedDisplay(RenderPanel renderer, Graphics2D g2d, Rectangle bounds, long ticks, int iconTicks) {
|
||||||
|
DrawingUtil.drawGradientRect(g2d, 60, TOPBAR_HEIGHT, W - 120, MAINBAR_HEIGHT, 20, BG_BLUE.darker(), BG_BLUE.brighter());
|
||||||
|
g2d.setFont(font);
|
||||||
|
FontMetrics fontMetrics = g2d.getFontMetrics();
|
||||||
|
g2d.setColor(BG_BLUE.darker());
|
||||||
|
g2d.drawRect(60 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET, W - 120 - STROKE_WIDTH, MAINBAR_HEIGHT - STROKE_WIDTH);
|
||||||
|
for (int i = 0; i < Math.min(9, lines.length - this.stringOffset); i++)
|
||||||
|
{
|
||||||
|
if (lines[i + stringOffset].startsWith("*") && lines[i].endsWith("*"))
|
||||||
|
{
|
||||||
|
String line = lines[i + stringOffset].substring(1, lines[i + stringOffset].length() - 1);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i * 30, "*", Color.WHITE, Color.BLACK, 2);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET + (W - 150 - STROKE_WIDTH) / 2 - fontMetrics.stringWidth(line) / 2, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i * 30, line, Color.WHITE, Color.BLACK, 2);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, W - 95 - STROKE_WIDTH, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i * 30, "*", Color.WHITE, Color.BLACK, 2);
|
||||||
|
}
|
||||||
|
else if (lines[i + stringOffset].startsWith("[") && lines[i].endsWith("]"))
|
||||||
|
{
|
||||||
|
String line = lines[i + stringOffset].substring(1, lines[i + stringOffset].length() - 1);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET + (W - 150 - STROKE_WIDTH) / 2 - fontMetrics.stringWidth(line) / 2, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i * 30, line, Color.WHITE, Color.BLACK, 2);
|
||||||
|
}
|
||||||
|
else DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i * 30, lines[i + stringOffset], Color.WHITE, Color.BLACK, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void redrawRegionlost(RenderPanel renderer) {
|
||||||
|
renderer.addRedrawBound(TOPBAR_HEIGHT, W - 120, MAINBAR_HEIGHT, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.flaremicro.visualforecast.displays;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.flaremicro.visualforecast.PropertyManager;
|
||||||
|
|
||||||
|
public class DisplayFactory {
|
||||||
|
int currentIndex = -1;
|
||||||
|
String indexValue = "";
|
||||||
|
|
||||||
|
private List<String> nameOrder = new ArrayList<String>();
|
||||||
|
private Map<String, Display> displays = new HashMap<String, Display>();
|
||||||
|
|
||||||
|
public DisplayFactory(PropertyManager propertyManager)
|
||||||
|
{
|
||||||
|
displays.put("message", new MessageForecastDisplay());
|
||||||
|
displays.put("day", new DayForecastDisplay());
|
||||||
|
displays.put("hourly", new HourlyForecastDisplay());
|
||||||
|
nameOrder.add("message");
|
||||||
|
nameOrder.add("day");
|
||||||
|
nameOrder.add("hourly");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Display nextDisplay() {
|
||||||
|
currentIndex = (currentIndex + 1) % nameOrder.size();
|
||||||
|
return displays.get(nameOrder.get(currentIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -31,7 +31,6 @@ import com.flaremicro.visualforecast.graphics.RenderConstants;
|
|||||||
import com.flaremicro.visualforecast.icons.IconProvider;
|
import com.flaremicro.visualforecast.icons.IconProvider;
|
||||||
|
|
||||||
public class HourlyForecastDisplay implements Display {
|
public class HourlyForecastDisplay implements Display {
|
||||||
private int dayOffset = 0;
|
|
||||||
private Font font;
|
private Font font;
|
||||||
private Font smallFont;
|
private Font smallFont;
|
||||||
private ForecastDetails details;
|
private ForecastDetails details;
|
||||||
@@ -41,7 +40,7 @@ public class HourlyForecastDisplay implements Display {
|
|||||||
private int ticksBeforeChange = 200;
|
private int ticksBeforeChange = 200;
|
||||||
private int animationTicks = -1;
|
private int animationTicks = -1;
|
||||||
|
|
||||||
private byte[] dewval = null;
|
private byte[] windchill = null;
|
||||||
private byte[] tempval = null;
|
private byte[] tempval = null;
|
||||||
private float[] percipval = null;
|
private float[] percipval = null;
|
||||||
|
|
||||||
@@ -56,7 +55,26 @@ public class HourlyForecastDisplay implements Display {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(RenderPanel renderer, long ticks, int iconTicks) {
|
public void tick(RenderPanel renderer, long ticks, int iconTicks) {
|
||||||
|
ticksBeforeChange--;
|
||||||
|
if (ticksBeforeChange <= 0)
|
||||||
|
{
|
||||||
|
ticksBeforeChange = 200;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
townIndex++;
|
||||||
|
if (details == null || townIndex >= details.getTownForecast().length)
|
||||||
|
{
|
||||||
|
renderer.nextDisplay();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.currentTown = details.getTownForecast()[townIndex];
|
||||||
|
}
|
||||||
|
while (this.currentTown == null || currentTown.getHourlyForecast() == null || currentTown.getHourlyForecast().length == 0);
|
||||||
|
renderer.setCurrentTown(currentTown.getTownName());
|
||||||
|
setGraphValues(currentTown);
|
||||||
|
renderer.requestFullRepaint();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setGraphValues(TownForecast town) {
|
public void setGraphValues(TownForecast town) {
|
||||||
@@ -66,12 +84,12 @@ public class HourlyForecastDisplay implements Display {
|
|||||||
if (forecast != null && forecast.length > 0)
|
if (forecast != null && forecast.length > 0)
|
||||||
{
|
{
|
||||||
int size = Math.min(12, forecast.length);
|
int size = Math.min(12, forecast.length);
|
||||||
dewval = new byte[size];
|
windchill = new byte[size];
|
||||||
tempval = new byte[size];
|
tempval = new byte[size];
|
||||||
percipval = new float[size];
|
percipval = new float[size];
|
||||||
for (int i = 0; i < size; i++)
|
for (int i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
dewval[i] = forecast[i].dewPoint;
|
windchill[i] = forecast[i].windChill;
|
||||||
tempval[i] = forecast[i].temp;
|
tempval[i] = forecast[i].temp;
|
||||||
percipval[i] = forecast[i].percip;
|
percipval[i] = forecast[i].percip;
|
||||||
}
|
}
|
||||||
@@ -133,15 +151,17 @@ public class HourlyForecastDisplay implements Display {
|
|||||||
FontMetrics fm = g2d.getFontMetrics();
|
FontMetrics fm = g2d.getFontMetrics();
|
||||||
|
|
||||||
DrawingUtil.drawOutlinedString(g2d, 100, RenderConstants.TOPBAR_HEIGHT + 35, "Temperature\u00B0c", Color.RED, Color.BLACK, 2);
|
DrawingUtil.drawOutlinedString(g2d, 100, RenderConstants.TOPBAR_HEIGHT + 35, "Temperature\u00B0c", Color.RED, Color.BLACK, 2);
|
||||||
DrawingUtil.drawOutlinedString(g2d, 260, RenderConstants.TOPBAR_HEIGHT + 35, "Dew point\u00B0c", Color.WHITE, Color.BLACK, 2);
|
DrawingUtil.drawOutlinedString(g2d, 260, RenderConstants.TOPBAR_HEIGHT + 35, "Wind Chill\u00B0c", Color.WHITE, Color.BLACK, 2);
|
||||||
DrawingUtil.drawOutlinedString(g2d, 410, RenderConstants.TOPBAR_HEIGHT + 35, "Precipitation%", Color.CYAN, Color.BLACK, 2);
|
DrawingUtil.drawOutlinedString(g2d, 410, RenderConstants.TOPBAR_HEIGHT + 35, "Precipitation%", Color.CYAN, Color.BLACK, 2);
|
||||||
|
|
||||||
|
g2d.setFont(font.deriveFont(20F));
|
||||||
String minText = min + "\u00B0";
|
String minText = min + "\u00B0";
|
||||||
String maxText = max + "\u00B0";
|
String maxText = max + "\u00B0";
|
||||||
|
|
||||||
DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + 40 - fm.stringWidth(maxText), RenderConstants.TOPBAR_HEIGHT + 53, maxText, Color.YELLOW, Color.BLACK, 2);
|
DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + 38 - fm.stringWidth(maxText), RenderConstants.TOPBAR_HEIGHT + 53, maxText, Color.YELLOW, Color.BLACK, 2);
|
||||||
DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + 40 - fm.stringWidth(minText), RenderConstants.TOPBAR_HEIGHT + MAINBAR_HEIGHT - 92, minText, Color.YELLOW, Color.BLACK, 2);
|
DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + 38 - fm.stringWidth(minText), RenderConstants.TOPBAR_HEIGHT + MAINBAR_HEIGHT - 92, minText, Color.YELLOW, Color.BLACK, 2);
|
||||||
|
|
||||||
|
g2d.setFont(font.deriveFont(20F));
|
||||||
g2d.setColor(RenderConstants.BG_ORANGE.darker());
|
g2d.setColor(RenderConstants.BG_ORANGE.darker());
|
||||||
g2d.drawLine(RenderConstants.SIDE_OFFSET + 40, (RenderConstants.TOPBAR_HEIGHT + 50), (RenderConstants.W - RenderConstants.SIDE_OFFSET - 20), (RenderConstants.TOPBAR_HEIGHT + 50));
|
g2d.drawLine(RenderConstants.SIDE_OFFSET + 40, (RenderConstants.TOPBAR_HEIGHT + 50), (RenderConstants.W - RenderConstants.SIDE_OFFSET - 20), (RenderConstants.TOPBAR_HEIGHT + 50));
|
||||||
|
|
||||||
@@ -150,6 +170,7 @@ public class HourlyForecastDisplay implements Display {
|
|||||||
|
|
||||||
//BlackLines
|
//BlackLines
|
||||||
|
|
||||||
|
g2d.setFont(smallFont.deriveFont(20F));
|
||||||
if (max > 0 && min < 0)
|
if (max > 0 && min < 0)
|
||||||
{
|
{
|
||||||
int nextTemp = (RenderConstants.TOPBAR_HEIGHT + RenderConstants.MAINBAR_HEIGHT - 94) + (int) (((min) / (float) range) * (RenderConstants.MAINBAR_HEIGHT - 144));
|
int nextTemp = (RenderConstants.TOPBAR_HEIGHT + RenderConstants.MAINBAR_HEIGHT - 94) + (int) (((min) / (float) range) * (RenderConstants.MAINBAR_HEIGHT - 144));
|
||||||
@@ -166,10 +187,10 @@ public class HourlyForecastDisplay implements Display {
|
|||||||
|
|
||||||
g2d.translate(2, 2);
|
g2d.translate(2, 2);
|
||||||
g2d.setColor(Color.BLACK);
|
g2d.setColor(Color.BLACK);
|
||||||
this.graphTemp(g2d, this.dewval, min, slotWidth, range, RenderConstants.MAINBAR_HEIGHT - 144);
|
this.graphTemp(g2d, this.windchill, min, slotWidth, range, RenderConstants.MAINBAR_HEIGHT - 144);
|
||||||
g2d.setColor(Color.WHITE);
|
g2d.setColor(Color.WHITE);
|
||||||
g2d.translate(-2, -2);
|
g2d.translate(-2, -2);
|
||||||
this.graphTemp(g2d, this.dewval, min, slotWidth, range, RenderConstants.MAINBAR_HEIGHT - 144);
|
this.graphTemp(g2d, this.windchill, min, slotWidth, range, RenderConstants.MAINBAR_HEIGHT - 144);
|
||||||
|
|
||||||
g2d.translate(2, 2);
|
g2d.translate(2, 2);
|
||||||
g2d.setColor(Color.BLACK);
|
g2d.setColor(Color.BLACK);
|
||||||
@@ -196,6 +217,7 @@ public class HourlyForecastDisplay implements Display {
|
|||||||
for (int i = 0; i < Math.min(12, forecast.length); i++)
|
for (int i = 0; i < Math.min(12, forecast.length); i++)
|
||||||
{
|
{
|
||||||
String timeString = simpleDateFormat.format(forecast[i].hour);
|
String timeString = simpleDateFormat.format(forecast[i].hour);
|
||||||
|
timeString = timeString.substring(0, timeString.length() - 1);
|
||||||
if ((i % 2) == 0)
|
if ((i % 2) == 0)
|
||||||
DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + 40 + slotWidth / 2 + (slotWidth * i) - fm.stringWidth(timeString) / 2, RenderConstants.TOPBAR_HEIGHT + MAINBAR_HEIGHT - 70, timeString, Color.YELLOW, Color.BLACK, 2);
|
DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + 40 + slotWidth / 2 + (slotWidth * i) - fm.stringWidth(timeString) / 2, RenderConstants.TOPBAR_HEIGHT + MAINBAR_HEIGHT - 70, timeString, Color.YELLOW, Color.BLACK, 2);
|
||||||
else DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + 40 + slotWidth / 2 + (slotWidth * i) - fm.stringWidth(timeString) / 2, RenderConstants.TOPBAR_HEIGHT + MAINBAR_HEIGHT - 60, timeString, Color.YELLOW, Color.BLACK, 2);
|
else DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + 40 + slotWidth / 2 + (slotWidth * i) - fm.stringWidth(timeString) / 2, RenderConstants.TOPBAR_HEIGHT + MAINBAR_HEIGHT - 60, timeString, Color.YELLOW, Color.BLACK, 2);
|
||||||
@@ -210,13 +232,13 @@ public class HourlyForecastDisplay implements Display {
|
|||||||
for (int i = 0; i < forecast.length; i++)
|
for (int i = 0; i < forecast.length; i++)
|
||||||
{
|
{
|
||||||
int currMin;
|
int currMin;
|
||||||
if (ValueCheck.valueNoData(forecast[i].dewPoint) && ValueCheck.valueNoData(forecast[i].temp))
|
if (ValueCheck.valueNoData(forecast[i].windChill) && ValueCheck.valueNoData(forecast[i].temp))
|
||||||
continue;
|
continue;
|
||||||
else if (ValueCheck.valueNoData(forecast[i].dewPoint))
|
else if (ValueCheck.valueNoData(forecast[i].windChill))
|
||||||
currMin = forecast[i].temp;
|
currMin = forecast[i].temp;
|
||||||
else if (ValueCheck.valueNoData(forecast[i].temp))
|
else if (ValueCheck.valueNoData(forecast[i].temp))
|
||||||
currMin = forecast[i].dewPoint;
|
currMin = forecast[i].windChill;
|
||||||
else currMin = Math.min(forecast[i].temp, forecast[i].dewPoint);
|
else currMin = Math.min(forecast[i].temp, forecast[i].windChill);
|
||||||
if (currMin < min)
|
if (currMin < min)
|
||||||
min = currMin;
|
min = currMin;
|
||||||
}
|
}
|
||||||
@@ -228,13 +250,13 @@ public class HourlyForecastDisplay implements Display {
|
|||||||
for (int i = 0; i < forecast.length; i++)
|
for (int i = 0; i < forecast.length; i++)
|
||||||
{
|
{
|
||||||
int currMax;
|
int currMax;
|
||||||
if (ValueCheck.valueNoData(forecast[i].dewPoint) && ValueCheck.valueNoData(forecast[i].temp))
|
if (ValueCheck.valueNoData(forecast[i].windChill) && ValueCheck.valueNoData(forecast[i].temp))
|
||||||
continue;
|
continue;
|
||||||
else if (ValueCheck.valueNoData(forecast[i].dewPoint))
|
else if (ValueCheck.valueNoData(forecast[i].windChill))
|
||||||
currMax = forecast[i].temp;
|
currMax = forecast[i].temp;
|
||||||
else if (ValueCheck.valueNoData(forecast[i].temp))
|
else if (ValueCheck.valueNoData(forecast[i].temp))
|
||||||
currMax = forecast[i].dewPoint;
|
currMax = forecast[i].windChill;
|
||||||
else currMax = Math.max(forecast[i].temp, forecast[i].dewPoint);
|
else currMax = Math.max(forecast[i].temp, forecast[i].windChill);
|
||||||
if (currMax > max)
|
if (currMax > max)
|
||||||
max = currMax;
|
max = currMax;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package com.flaremicro.visualforecast.displays;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.flaremicro.visualforecast.RenderPanel;
|
||||||
|
import com.flaremicro.visualforecast.api.ForecastProvider;
|
||||||
|
import com.flaremicro.visualforecast.graphics.DrawingUtil;
|
||||||
|
import com.flaremicro.visualforecast.graphics.FontManager;
|
||||||
|
|
||||||
|
import static com.flaremicro.visualforecast.graphics.RenderConstants.*;
|
||||||
|
|
||||||
|
public class MessageForecastDisplay implements Display {
|
||||||
|
|
||||||
|
private String[] lines = new String[0];
|
||||||
|
private Font font;
|
||||||
|
|
||||||
|
private int stringOffset = 0;
|
||||||
|
private int ticksBeforeChange = 0;
|
||||||
|
|
||||||
|
public MessageForecastDisplay() {
|
||||||
|
font = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf")).deriveFont(30F);
|
||||||
|
|
||||||
|
/*
|
||||||
|
int w2 = g2d.getFontMetrics().stringWidth("EXTREME WEATHER ADVISORY");
|
||||||
|
drawOutlinedString(g2d, (W >> 1) - (w2 >> 1), TOPBAR_HEIGHT + 48, "EXTREME WEATHER ADVISORY", Color.RED, Color.BLACK, 2);
|
||||||
|
|
||||||
|
g2d.setFont(font.deriveFont(30F));
|
||||||
|
for (int i = 0; i < testString.length; i++)
|
||||||
|
{
|
||||||
|
drawOutlinedString(g2d, 90, TOPBAR_HEIGHT + 78 + 25 * i, testString[i], Color.WHITE, Color.BLACK, 1);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(RenderPanel renderer, long ticks, int iconTicks) {
|
||||||
|
ticksBeforeChange--;
|
||||||
|
if (ticksBeforeChange <= 0)
|
||||||
|
{
|
||||||
|
stringOffset += 9;
|
||||||
|
if (stringOffset < lines.length)
|
||||||
|
{
|
||||||
|
ticksBeforeChange = 200;
|
||||||
|
renderer.requestExclusiveBoundedRepaint();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
renderer.nextDisplay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initDisplay(RenderPanel renderer, ForecastProvider forecastProvider, long ticks, int iconTicks) {
|
||||||
|
ticksBeforeChange = 200;
|
||||||
|
stringOffset = 0;
|
||||||
|
String test = "*IMPORTANT NOTICE*\n*THIS BETA IS UNFINISHED*\n\nThis is a Beta version of the VisualForeast 1000! Many things are not finished, and only the hourly and 7 day forecasts are ready. There will be a lot more to come!\nPlease note that there are some issues with data collection from Environment Canada resulting in missing or potentially incorrect information around midnight hours. This will be fixed as the project continues and the disclaimer will be removed.";
|
||||||
|
ArrayList<String> linesList = new ArrayList<String>();
|
||||||
|
|
||||||
|
renderer.setCurrentForecast("Welcome to the");
|
||||||
|
renderer.setCurrentTown("VisualForecast 1000");
|
||||||
|
|
||||||
|
BufferedImage disposableImage = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY);
|
||||||
|
Graphics2D g = disposableImage.createGraphics();
|
||||||
|
FontMetrics f = g.getFontMetrics(font);
|
||||||
|
String[] lines = test.split("\n");
|
||||||
|
for (int i = 0; i < lines.length; i++)
|
||||||
|
{
|
||||||
|
splitText(lines[i], W - 150 - STROKE_WIDTH, f, linesList);
|
||||||
|
//if(words[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
g.dispose();
|
||||||
|
disposableImage.flush();
|
||||||
|
|
||||||
|
redrawRegionlost(renderer);
|
||||||
|
|
||||||
|
this.lines = linesList.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void splitText(String text, int maxWidth, FontMetrics fontMetrics, ArrayList<String> lineList) {
|
||||||
|
|
||||||
|
text = text.trim();
|
||||||
|
//this.text.add(text);
|
||||||
|
if (fontMetrics.stringWidth(text) <= maxWidth)
|
||||||
|
lineList.add(text);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (text.length() > 0)
|
||||||
|
{
|
||||||
|
int idx = binSearch(text, fontMetrics, maxWidth, 1, text.length());
|
||||||
|
if (idx <= 0)
|
||||||
|
break;
|
||||||
|
String texPart = text.substring(0, idx).trim();
|
||||||
|
if (fontMetrics.stringWidth(text.substring(0, Math.min(text.length(), idx + 1))) > maxWidth && texPart.contains(" "))
|
||||||
|
{
|
||||||
|
idx = texPart.lastIndexOf(" ");
|
||||||
|
texPart = texPart.substring(0, idx);
|
||||||
|
}
|
||||||
|
lineList.add(texPart);
|
||||||
|
text = text.substring(idx).trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int binSearch(String string, FontMetrics fontMetrics, int key, int low, int high) {
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
while (low <= high)
|
||||||
|
{
|
||||||
|
int mid = low + ((high - low) / 2);
|
||||||
|
int midmetric = fontMetrics.stringWidth(string.substring(0, mid));
|
||||||
|
if (midmetric < key)
|
||||||
|
{
|
||||||
|
low = mid + 1;
|
||||||
|
index = mid;
|
||||||
|
}
|
||||||
|
else if (midmetric > key)
|
||||||
|
{
|
||||||
|
high = mid - 1;
|
||||||
|
}
|
||||||
|
else if (midmetric == key)
|
||||||
|
{
|
||||||
|
index = mid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawDisplay(RenderPanel renderer, Graphics2D g2d, long ticks, int iconTicks) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawBoundLimitedDisplay(RenderPanel renderer, Graphics2D g2d, Rectangle bounds, long ticks, int iconTicks) {
|
||||||
|
DrawingUtil.drawGradientRect(g2d, 60, TOPBAR_HEIGHT, W - 120, MAINBAR_HEIGHT, 20, BG_BLUE.darker(), BG_BLUE.brighter());
|
||||||
|
g2d.setFont(font);
|
||||||
|
FontMetrics fontMetrics = g2d.getFontMetrics();
|
||||||
|
g2d.setColor(BG_BLUE.darker());
|
||||||
|
g2d.drawRect(60 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET, W - 120 - STROKE_WIDTH, MAINBAR_HEIGHT - STROKE_WIDTH);
|
||||||
|
for (int i = 0; i < Math.min(9, lines.length - this.stringOffset); i++)
|
||||||
|
{
|
||||||
|
if (lines[i + stringOffset].startsWith("*") && lines[i].endsWith("*"))
|
||||||
|
{
|
||||||
|
String line = lines[i + stringOffset].substring(1, lines[i + stringOffset].length() - 1);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i * 30, "*", Color.WHITE, Color.BLACK, 2);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET + (W - 150 - STROKE_WIDTH) / 2 - fontMetrics.stringWidth(line) / 2, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i * 30, line, Color.WHITE, Color.BLACK, 2);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, W - 95 - STROKE_WIDTH, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i * 30, "*", Color.WHITE, Color.BLACK, 2);
|
||||||
|
}
|
||||||
|
else if (lines[i + stringOffset].startsWith("[") && lines[i].endsWith("]"))
|
||||||
|
{
|
||||||
|
String line = lines[i + stringOffset].substring(1, lines[i + stringOffset].length() - 1);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET + (W - 150 - STROKE_WIDTH) / 2 - fontMetrics.stringWidth(line) / 2, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i * 30, line, Color.WHITE, Color.BLACK, 2);
|
||||||
|
}
|
||||||
|
else DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i * 30, lines[i + stringOffset], Color.WHITE, Color.BLACK, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void redrawRegionlost(RenderPanel renderer) {
|
||||||
|
renderer.addRedrawBound(TOPBAR_HEIGHT, W - 120, MAINBAR_HEIGHT, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,155 @@
|
|||||||
|
package com.flaremicro.visualforecast.displays;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.FontMetrics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.flaremicro.visualforecast.RenderPanel;
|
||||||
|
import com.flaremicro.visualforecast.api.ForecastProvider;
|
||||||
|
import com.flaremicro.visualforecast.graphics.DrawingUtil;
|
||||||
|
import com.flaremicro.visualforecast.graphics.FontManager;
|
||||||
|
|
||||||
|
import static com.flaremicro.visualforecast.graphics.RenderConstants.*;
|
||||||
|
|
||||||
|
public class ThirtySixHourDisplay implements Display {
|
||||||
|
|
||||||
|
private String[] lines = new String[0];
|
||||||
|
private Font font;
|
||||||
|
|
||||||
|
|
||||||
|
public ThirtySixHourDisplay() {
|
||||||
|
font = FontManager.getInstance().getOrCreateFont(Font.TRUETYPE_FONT, this.getClass().getResource("/Star4000.ttf")).deriveFont(30F);
|
||||||
|
|
||||||
|
/*
|
||||||
|
int w2 = g2d.getFontMetrics().stringWidth("EXTREME WEATHER ADVISORY");
|
||||||
|
drawOutlinedString(g2d, (W >> 1) - (w2 >> 1), TOPBAR_HEIGHT + 48, "EXTREME WEATHER ADVISORY", Color.RED, Color.BLACK, 2);
|
||||||
|
|
||||||
|
g2d.setFont(font.deriveFont(30F));
|
||||||
|
for (int i = 0; i < testString.length; i++)
|
||||||
|
{
|
||||||
|
drawOutlinedString(g2d, 90, TOPBAR_HEIGHT + 78 + 25 * i, testString[i], Color.WHITE, Color.BLACK, 1);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(RenderPanel renderer, long ticks, int iconTicks) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initDisplay(RenderPanel renderer, ForecastProvider forecastProvider, long ticks, int iconTicks) {
|
||||||
|
String test = "*IMPORTANT NOTICE*\n*POWER OUTAGE POSSIBLE*\n*DUE TO EXTREME WINDS*\n\nHurricane-force winds capable of reaching 127km/h will be hitting the east coast around noon tomorrow. Keep windows and doors barricaded to prevent";
|
||||||
|
ArrayList<String> linesList = new ArrayList<String>();
|
||||||
|
|
||||||
|
BufferedImage disposableImage = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY);
|
||||||
|
Graphics2D g = disposableImage.createGraphics();
|
||||||
|
FontMetrics f = g.getFontMetrics(font);
|
||||||
|
System.out.println("yas2");
|
||||||
|
String[] lines = test.split("\n");
|
||||||
|
for(int i = 0; i < lines.length; i++)
|
||||||
|
{
|
||||||
|
splitText(lines[i], W - 150 - STROKE_WIDTH, f, linesList);
|
||||||
|
//if(words[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
g.dispose();
|
||||||
|
disposableImage.flush();
|
||||||
|
|
||||||
|
System.out.println("yas");
|
||||||
|
|
||||||
|
this.lines = linesList.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void splitText(String text, int maxWidth, FontMetrics fontMetrics, ArrayList<String> lineList) {
|
||||||
|
|
||||||
|
text = text.trim();
|
||||||
|
//this.text.add(text);
|
||||||
|
if (fontMetrics.stringWidth(text) <= maxWidth)
|
||||||
|
lineList.add(text);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
while (text.length() > 0)
|
||||||
|
{
|
||||||
|
int idx = binSearch(text, fontMetrics, maxWidth, 1, text.length());
|
||||||
|
if (idx <= 0)
|
||||||
|
break;
|
||||||
|
String texPart = text.substring(0, idx).trim();
|
||||||
|
if (fontMetrics.stringWidth(text.substring(0, Math.min(text.length(), idx + 1))) > maxWidth && texPart.contains(" "))
|
||||||
|
{
|
||||||
|
idx = texPart.lastIndexOf(" ");
|
||||||
|
texPart = texPart.substring(0, idx);
|
||||||
|
}
|
||||||
|
lineList.add(texPart);
|
||||||
|
text = text.substring(idx).trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int binSearch(String string, FontMetrics fontMetrics, int key, int low, int high) {
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
while (low <= high)
|
||||||
|
{
|
||||||
|
int mid = low + ((high - low) / 2);
|
||||||
|
int midmetric = fontMetrics.stringWidth(string.substring(0, mid));
|
||||||
|
if (midmetric < key)
|
||||||
|
{
|
||||||
|
low = mid + 1;
|
||||||
|
index = mid;
|
||||||
|
}
|
||||||
|
else if (midmetric > key)
|
||||||
|
{
|
||||||
|
high = mid - 1;
|
||||||
|
}
|
||||||
|
else if (midmetric == key)
|
||||||
|
{
|
||||||
|
index = mid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawDisplay(RenderPanel renderer, Graphics2D g2d, long ticks, int iconTicks) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawBoundLimitedDisplay(RenderPanel renderer, Graphics2D g2d, Rectangle bounds, long ticks, int iconTicks) {
|
||||||
|
DrawingUtil.drawGradientRect(g2d, 60, TOPBAR_HEIGHT, W - 120, MAINBAR_HEIGHT, 20, BG_BLUE.brighter(), BG_BLUE.darker());
|
||||||
|
g2d.setFont(font);
|
||||||
|
FontMetrics fontMetrics = g2d.getFontMetrics();
|
||||||
|
g2d.setColor(BG_BLUE.brighter());
|
||||||
|
g2d.drawRect(60 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET, W - 120 - STROKE_WIDTH, MAINBAR_HEIGHT - STROKE_WIDTH);
|
||||||
|
for(int i = 0; i < lines.length; i++)
|
||||||
|
{
|
||||||
|
if(lines[i].startsWith("*") && lines[i].endsWith("*"))
|
||||||
|
{
|
||||||
|
String line = lines[i].substring(1, lines[i].length()-1);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i*30, "*", Color.WHITE, Color.BLACK, 2);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET + (W - 150 - STROKE_WIDTH)/2 - fontMetrics.stringWidth(line)/2, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i*30, line, Color.WHITE, Color.BLACK, 2);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, W - 95 - STROKE_WIDTH, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i*30, "*", Color.WHITE, Color.BLACK, 2);
|
||||||
|
}
|
||||||
|
else if(lines[i].startsWith("[") && lines[i].endsWith("]"))
|
||||||
|
{
|
||||||
|
String line = lines[i].substring(1, lines[i].length()-1);
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET + (W - 150 - STROKE_WIDTH)/2 - fontMetrics.stringWidth(line)/2, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i*30, line, Color.WHITE, Color.BLACK, 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DrawingUtil.drawOutlinedString(g2d, 60 + 20 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET + 40 + i*30, lines[i], Color.WHITE, Color.BLACK, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void redrawRegionlost(RenderPanel renderer) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -10,15 +10,15 @@ public class HourlyForecast {
|
|||||||
public final byte temp;
|
public final byte temp;
|
||||||
public final short windSpeed;
|
public final short windSpeed;
|
||||||
public final float percip;
|
public final float percip;
|
||||||
public final byte dewPoint;
|
public final byte windChill;
|
||||||
|
|
||||||
public HourlyForecast(Date hour, byte iconId, byte temp, short windSpeed, float percip, byte dewPoint)
|
public HourlyForecast(Date hour, byte iconId, byte temp, short windSpeed, float percip, byte windChill)
|
||||||
{
|
{
|
||||||
this.hour = hour;
|
this.hour = hour;
|
||||||
this.iconId = (byte) (iconId % IconProvider.INDEXED_ICONS.length);
|
this.iconId = (byte) (iconId % IconProvider.INDEXED_ICONS.length);
|
||||||
this.temp = temp;
|
this.temp = temp;
|
||||||
this.windSpeed = windSpeed;
|
this.windSpeed = windSpeed;
|
||||||
this.percip = percip;
|
this.percip = percip;
|
||||||
this.dewPoint = dewPoint;
|
this.windChill = windChill;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
package com.flaremicro.visualforecast.forecast;
|
package com.flaremicro.visualforecast.forecast;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
public class TownForecast {
|
public class TownForecast {
|
||||||
public TownForecast(String townName, DayForecast[] dayForecast) {
|
public TownForecast(String townName, DayForecast[] dayForecast) {
|
||||||
this.townName = townName;
|
this.townName = townName;
|
||||||
@@ -8,8 +13,25 @@ public class TownForecast {
|
|||||||
|
|
||||||
private final String townName;
|
private final String townName;
|
||||||
private final DayForecast[] dayForecast;
|
private final DayForecast[] dayForecast;
|
||||||
|
private Set<String> displays = new HashSet<String>();
|
||||||
|
|
||||||
|
|
||||||
private HourlyForecast[] hourlyForecast;
|
private HourlyForecast[] hourlyForecast;
|
||||||
|
|
||||||
|
public boolean isDisplaySupported(String displayName)
|
||||||
|
{
|
||||||
|
return displays.size() == 0 || displays.contains(displayName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSupportedDisplays(String ... displays){
|
||||||
|
setSupportedDisplays(Arrays.asList(displays));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSupportedDisplays(Collection<String> displays){
|
||||||
|
this.displays.clear();
|
||||||
|
this.displays.addAll(displays);
|
||||||
|
}
|
||||||
|
|
||||||
public void setHourlyForecast(HourlyForecast[] forecast) {
|
public void setHourlyForecast(HourlyForecast[] forecast) {
|
||||||
this.hourlyForecast = forecast;
|
this.hourlyForecast = forecast;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#VisualForecast 1000 Properties file. Functional provider must be set for successful boot!
|
#VisualForecast 1000 Properties file. Functional provider must be set for successful boot!
|
||||||
#Sat Mar 09 23:49:43 PST 2024
|
#Fri Mar 15 19:46:22 PDT 2024
|
||||||
forecast-provider-jar=MockForecastProvider.jar
|
forecast-provider-jar=CanadaDatamartProvider.jar
|
||||||
|
|||||||
Reference in New Issue
Block a user