From 0648a0178c59b51cdc396c5101ce15c94576aa07 Mon Sep 17 00:00:00 2001 From: Vulpovile Date: Wed, 9 Apr 2025 21:52:18 -0700 Subject: [PATCH] A lot --- .classpath | 1 + CanadaDatamartProvider.jar | Bin 15055 -> 18058 bytes CanadaDatamartProvider.properties | 13 +- .../visualforecast/PropertyManager.java | 107 ++++++++---- .../visualforecast/RenderPanel.java | 42 +++-- .../visualforecast/VisualForecastFrame.java | 7 +- .../visualforecast/displays/Display.java | 2 + .../displays/DisplayFactory.java | 62 +++++-- .../visualforecast/displays/TextDisplay.java | 55 ------- .../displays/ThirtySixHourDisplay.java | 155 ------------------ .../displays/{ => impl}/BootupDisplay.java | 10 +- .../{ => impl}/CurrentForecastDisplay.java | 13 +- .../{ => impl}/HourlyForecastDisplay.java | 16 +- .../{ => impl}/MessageForecastDisplay.java | 9 +- .../SevenDayForecastDisplay.java} | 47 ++++-- .../SevenDayForecastDisplayOldAnimation.java} | 12 +- .../forecast/CurrentConditions.java | 20 +++ .../visualforecast/forecast/TownForecast.java | 24 ++- .../visualforecast/icons/IconProvider.java | 2 +- .../visualforecast/icons/impl/ButterIcon.java | 1 + .../icons/impl/InvalidIcon.java | 1 + vf1000.properties | 6 +- 22 files changed, 288 insertions(+), 317 deletions(-) delete mode 100644 src/com/flaremicro/visualforecast/displays/TextDisplay.java delete mode 100644 src/com/flaremicro/visualforecast/displays/ThirtySixHourDisplay.java rename src/com/flaremicro/visualforecast/displays/{ => impl}/BootupDisplay.java (91%) rename src/com/flaremicro/visualforecast/displays/{ => impl}/CurrentForecastDisplay.java (95%) rename src/com/flaremicro/visualforecast/displays/{ => impl}/HourlyForecastDisplay.java (97%) rename src/com/flaremicro/visualforecast/displays/{ => impl}/MessageForecastDisplay.java (97%) rename src/com/flaremicro/visualforecast/displays/{DayForecastDisplay.java => impl/SevenDayForecastDisplay.java} (93%) rename src/com/flaremicro/visualforecast/displays/{DayForecastDisplayOldAnimation.java => impl/SevenDayForecastDisplayOldAnimation.java} (97%) create mode 100644 src/com/flaremicro/visualforecast/forecast/CurrentConditions.java diff --git a/.classpath b/.classpath index ad3f9d4..6a512aa 100644 --- a/.classpath +++ b/.classpath @@ -3,5 +3,6 @@ + diff --git a/CanadaDatamartProvider.jar b/CanadaDatamartProvider.jar index 2c9f0d6b59d4a80b10f52312a97ee349427e5e79..adb17af29b263bcb72ab5b6e0539ae91daae8bb4 100644 GIT binary patch delta 15547 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 Vz&}{^zs7ID#8Mt&NUncZ`G032vJ3zK delta 12552 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 nameOrder = new ArrayList(); private Map displays = new HashMap(); - - 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 DisplayFactory(PropertyManager propertyManager) { + this.propertyManager = propertyManager; + nameOrder.add(register(new MessageForecastDisplay())); + //nameOrder.add(register(new CurrentForecastDisplay())); + nameOrder.add(register(new ThirtySixHourForecastDisplay())); + nameOrder.add(register(new SevenDayForecastDisplay())); + nameOrder.add(register(new HourlyForecastDisplay())); + int selection = propertyManager.getInteger("current-display-version", -1); + + String nameOrderString = getCurrentNameOrder(); + if ((selection >= 0 && selection != CURRENT_SELECTION)) + { + propertyManager.setInteger("current-display-version", CURRENT_SELECTION); + propertyManager.setString("display-selection", nameOrderString); + propertyManager.store(); + } + else + { + System.out.println("got good order: " + propertyManager.getString("display-selection", "oh no")); + nameOrder.clear(); + String[] s = propertyManager.getString("display-selection", nameOrderString).split(","); + nameOrder.addAll(Arrays.asList(s)); + } + } + + private String getCurrentNameOrder() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < nameOrder.size(); i++) + { + if (i != 0) + { + sb.append(","); + } + sb.append(nameOrder.get(i)); + } + return sb.toString(); + } + + private String register(Display display) { + displays.put(display.getDisplayName(), display); + return display.getDisplayName(); } public Display nextDisplay() { currentIndex = (currentIndex + 1) % nameOrder.size(); return displays.get(nameOrder.get(currentIndex)); } - + } diff --git a/src/com/flaremicro/visualforecast/displays/TextDisplay.java b/src/com/flaremicro/visualforecast/displays/TextDisplay.java deleted file mode 100644 index 56832c6..0000000 --- a/src/com/flaremicro/visualforecast/displays/TextDisplay.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.flaremicro.visualforecast.displays; - -import java.awt.Graphics2D; -import java.awt.Rectangle; - -import com.flaremicro.visualforecast.RenderPanel; -import com.flaremicro.visualforecast.api.ForecastProvider; -import com.flaremicro.visualforecast.graphics.DrawingUtil; - -import static com.flaremicro.visualforecast.graphics.RenderConstants.*; - -public class TextDisplay implements Display { - - public TextDisplay(String title, String scrollText) { - /* - int w2 = g2d.getFontMetrics().stringWidth("EXTREME WEATHER ADVISORY"); - drawOutlinedString(g2d, (W >> 1) - (w2 >> 1), TOPBAR_HEIGHT + 48, "EXTREME WEATHER ADVISORY", Color.RED, Color.BLACK, 2); - - g2d.setFont(font.deriveFont(30F)); - for (int i = 0; i < testString.length; i++) - { - drawOutlinedString(g2d, 90, TOPBAR_HEIGHT + 78 + 25 * i, testString[i], Color.WHITE, Color.BLACK, 1); - } - */ - } - - @Override - public void tick(RenderPanel renderer, long ticks, int iconTicks) { - } - - @Override - public void initDisplay(RenderPanel renderer, ForecastProvider forecastProvider, long ticks, int iconTicks) { - } - - @Override - public void drawDisplay(RenderPanel renderer, Graphics2D g2d, long ticks, int iconTicks) { - DrawingUtil.drawGradientRect(g2d, 60, TOPBAR_HEIGHT, W - 120, MAINBAR_HEIGHT, 20, BG_BLUE.brighter(), BG_BLUE.darker()); - g2d.setColor(BG_BLUE.brighter()); - g2d.drawRect(60 + STROKE_OFFSET, TOPBAR_HEIGHT + STROKE_OFFSET, W - 120 - STROKE_WIDTH, MAINBAR_HEIGHT - STROKE_WIDTH); - - } - - @Override - public void drawBoundLimitedDisplay(RenderPanel renderer, Graphics2D g2d, Rectangle bounds, long ticks, int iconTicks) { - } - - @Override - public void redrawRegionlost(RenderPanel renderer) { - } - - @Override - public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) { - } - -} diff --git a/src/com/flaremicro/visualforecast/displays/ThirtySixHourDisplay.java b/src/com/flaremicro/visualforecast/displays/ThirtySixHourDisplay.java deleted file mode 100644 index bd57794..0000000 --- a/src/com/flaremicro/visualforecast/displays/ThirtySixHourDisplay.java +++ /dev/null @@ -1,155 +0,0 @@ -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 linesList = new ArrayList(); - - 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 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) { - } - -} diff --git a/src/com/flaremicro/visualforecast/displays/BootupDisplay.java b/src/com/flaremicro/visualforecast/displays/impl/BootupDisplay.java similarity index 91% rename from src/com/flaremicro/visualforecast/displays/BootupDisplay.java rename to src/com/flaremicro/visualforecast/displays/impl/BootupDisplay.java index e88be81..9964788 100644 --- a/src/com/flaremicro/visualforecast/displays/BootupDisplay.java +++ b/src/com/flaremicro/visualforecast/displays/impl/BootupDisplay.java @@ -1,4 +1,4 @@ -package com.flaremicro.visualforecast.displays; +package com.flaremicro.visualforecast.displays.impl; import java.awt.Color; import java.awt.Font; @@ -7,6 +7,7 @@ import java.awt.Rectangle; import com.flaremicro.visualforecast.RenderPanel; import com.flaremicro.visualforecast.api.ForecastProvider; +import com.flaremicro.visualforecast.displays.Display; import com.flaremicro.visualforecast.graphics.DrawingUtil; import com.flaremicro.visualforecast.graphics.FontManager; import com.flaremicro.visualforecast.graphics.RenderConstants; @@ -64,7 +65,7 @@ public class BootupDisplay implements Display { IconProvider.drawIcon(g2d, IconProvider.INDEXED_ICONS[i], x, y, 80, iconTicks); } g2d.setFont(font.deriveFont(40F)); - DrawingUtil.drawOutlinedString(g2d, RenderConstants.W / 2 - g2d.getFontMetrics().stringWidth("VisualForecast 1000") / 2, RenderConstants.H / 2, "VisualForecast 1000", Color.WHITE, Color.BLACK, 2); + //DrawingUtil.drawOutlinedString(g2d, RenderConstants.W / 2 - g2d.getFontMetrics().stringWidth("VisualForecast 1000") / 2, RenderConstants.H / 2, "VisualForecast 1000", Color.WHITE, Color.BLACK, 2); } else if (this.ticks > 90) { @@ -102,4 +103,9 @@ public class BootupDisplay implements Display { this.forecastReady = provider.isForecastReady(); } } + + @Override + public String getDisplayName() { + return "bootup"; + } } diff --git a/src/com/flaremicro/visualforecast/displays/CurrentForecastDisplay.java b/src/com/flaremicro/visualforecast/displays/impl/CurrentForecastDisplay.java similarity index 95% rename from src/com/flaremicro/visualforecast/displays/CurrentForecastDisplay.java rename to src/com/flaremicro/visualforecast/displays/impl/CurrentForecastDisplay.java index 7dd42cd..b32eec9 100644 --- a/src/com/flaremicro/visualforecast/displays/CurrentForecastDisplay.java +++ b/src/com/flaremicro/visualforecast/displays/impl/CurrentForecastDisplay.java @@ -1,4 +1,4 @@ -package com.flaremicro.visualforecast.displays; +package com.flaremicro.visualforecast.displays.impl; import java.awt.Color; import java.awt.Font; @@ -10,6 +10,7 @@ import java.util.ArrayList; import com.flaremicro.visualforecast.RenderPanel; import com.flaremicro.visualforecast.api.ForecastProvider; +import com.flaremicro.visualforecast.displays.Display; import com.flaremicro.visualforecast.graphics.DrawingUtil; import com.flaremicro.visualforecast.graphics.FontManager; @@ -63,8 +64,8 @@ public class CurrentForecastDisplay implements Display { 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 linesList = new ArrayList(); - renderer.setCurrentForecast("Welcome to the"); - renderer.setCurrentTown("VisualForecast 1000"); + renderer.setCurrentForecast("Current Conditions"); + renderer.setCurrentTown("TOWN NAME HERE"); BufferedImage disposableImage = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_GRAY); Graphics2D g = disposableImage.createGraphics(); @@ -171,5 +172,9 @@ public class CurrentForecastDisplay implements Display { @Override public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) { } - + + @Override + public String getDisplayName() { + return "current"; + } } diff --git a/src/com/flaremicro/visualforecast/displays/HourlyForecastDisplay.java b/src/com/flaremicro/visualforecast/displays/impl/HourlyForecastDisplay.java similarity index 97% rename from src/com/flaremicro/visualforecast/displays/HourlyForecastDisplay.java rename to src/com/flaremicro/visualforecast/displays/impl/HourlyForecastDisplay.java index 7e9a18d..872291c 100644 --- a/src/com/flaremicro/visualforecast/displays/HourlyForecastDisplay.java +++ b/src/com/flaremicro/visualforecast/displays/impl/HourlyForecastDisplay.java @@ -1,4 +1,4 @@ -package com.flaremicro.visualforecast.displays; +package com.flaremicro.visualforecast.displays.impl; import static com.flaremicro.visualforecast.graphics.RenderConstants.BG_BLUE; import static com.flaremicro.visualforecast.graphics.RenderConstants.MAINBAR_HEIGHT; @@ -9,18 +9,13 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.GradientPaint; import java.awt.Graphics2D; -import java.awt.Polygon; import java.awt.Rectangle; -import java.awt.Transparency; import java.awt.image.BufferedImage; import java.text.DateFormat; import java.text.SimpleDateFormat; -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.displays.Display; import com.flaremicro.visualforecast.forecast.ForecastDetails; import com.flaremicro.visualforecast.forecast.HourlyForecast; import com.flaremicro.visualforecast.forecast.TownForecast; @@ -70,7 +65,7 @@ public class HourlyForecastDisplay implements Display { } this.currentTown = details.getTownForecast()[townIndex]; } - while (this.currentTown == null || currentTown.getHourlyForecast() == null || currentTown.getHourlyForecast().length == 0); + while (this.currentTown == null || !currentTown.isDisplaySupported(this.getDisplayName()) || currentTown.getHourlyForecast() == null || currentTown.getHourlyForecast().length == 0); renderer.setCurrentTown(currentTown.getTownName()); setGraphValues(currentTown); renderer.requestFullRepaint(); @@ -346,4 +341,9 @@ public class HourlyForecastDisplay implements Display { public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) { } + + @Override + public String getDisplayName() { + return "hourly"; + } } diff --git a/src/com/flaremicro/visualforecast/displays/MessageForecastDisplay.java b/src/com/flaremicro/visualforecast/displays/impl/MessageForecastDisplay.java similarity index 97% rename from src/com/flaremicro/visualforecast/displays/MessageForecastDisplay.java rename to src/com/flaremicro/visualforecast/displays/impl/MessageForecastDisplay.java index 8909c99..b7b905e 100644 --- a/src/com/flaremicro/visualforecast/displays/MessageForecastDisplay.java +++ b/src/com/flaremicro/visualforecast/displays/impl/MessageForecastDisplay.java @@ -1,4 +1,4 @@ -package com.flaremicro.visualforecast.displays; +package com.flaremicro.visualforecast.displays.impl; import java.awt.Color; import java.awt.Font; @@ -10,6 +10,7 @@ import java.util.ArrayList; import com.flaremicro.visualforecast.RenderPanel; import com.flaremicro.visualforecast.api.ForecastProvider; +import com.flaremicro.visualforecast.displays.Display; import com.flaremicro.visualforecast.graphics.DrawingUtil; import com.flaremicro.visualforecast.graphics.FontManager; @@ -171,5 +172,9 @@ public class MessageForecastDisplay implements Display { @Override public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) { } - + + @Override + public String getDisplayName() { + return "message"; + } } diff --git a/src/com/flaremicro/visualforecast/displays/DayForecastDisplay.java b/src/com/flaremicro/visualforecast/displays/impl/SevenDayForecastDisplay.java similarity index 93% rename from src/com/flaremicro/visualforecast/displays/DayForecastDisplay.java rename to src/com/flaremicro/visualforecast/displays/impl/SevenDayForecastDisplay.java index a4e8614..d5ae977 100644 --- a/src/com/flaremicro/visualforecast/displays/DayForecastDisplay.java +++ b/src/com/flaremicro/visualforecast/displays/impl/SevenDayForecastDisplay.java @@ -1,4 +1,4 @@ -package com.flaremicro.visualforecast.displays; +package com.flaremicro.visualforecast.displays.impl; import static com.flaremicro.visualforecast.graphics.RenderConstants.MAINBAR_HEIGHT; @@ -16,6 +16,7 @@ import java.util.Locale; import com.flaremicro.visualforecast.RenderPanel; import com.flaremicro.visualforecast.api.ForecastProvider; +import com.flaremicro.visualforecast.displays.Display; import com.flaremicro.visualforecast.forecast.DayForecast; import com.flaremicro.visualforecast.forecast.ForecastDetails; import com.flaremicro.visualforecast.forecast.TownForecast; @@ -25,7 +26,7 @@ import com.flaremicro.visualforecast.graphics.FontManager; import com.flaremicro.visualforecast.graphics.RenderConstants; import com.flaremicro.visualforecast.icons.IconProvider; -public class DayForecastDisplay implements Display { +public class SevenDayForecastDisplay implements Display { private int dayOffset = 0; private Font font; private Font smallFont; @@ -40,14 +41,19 @@ public class DayForecastDisplay implements Display { private int ticksBeforeChange = 200; private int animationTicks = -1; - public DayForecastDisplay() { + public SevenDayForecastDisplay() { 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")); } + //TODO improve @Override public void tick(RenderPanel renderer, long ticks, int iconTicks) { - if (animationTicks >= 0) + if(details == null || details.getTownForecast() == null){ + renderer.nextDisplay(); + return; + } + else if (animationTicks >= 0) { animationTicks += 8; if (animationTicks > RenderConstants.W - 60) @@ -70,19 +76,23 @@ public class DayForecastDisplay implements Display { dayOffset = dayOffset + 4; if (dayOffset >= 8) { - dayOffset = 0; - townIndex++; - if (townIndex >= details.getTownForecast().length) + do { - renderer.nextDisplay(); - return; - } - else - { - previousTown = currentTown; - currentTown = details.getTownForecast()[townIndex]; - renderer.setCurrentTown(currentTown.getTownName()); + dayOffset = 0; + townIndex++; + if (townIndex >= details.getTownForecast().length) + { + renderer.nextDisplay(); + return; + } + else + { + previousTown = currentTown; + currentTown = details.getTownForecast()[townIndex]; + renderer.setCurrentTown(currentTown.getTownName()); + } } + while (this.currentTown != null && !this.currentTown.isDisplaySupported(this.getDisplayName())); } animationTicks = 0; @@ -225,7 +235,7 @@ public class DayForecastDisplay implements Display { g2d.setFont(smallFont.deriveFont(24F)); DrawingUtil.drawOutlinedString(g2d, RenderConstants.SIDE_OFFSET + (131 * i) + 20, RenderConstants.TOPBAR_HEIGHT + 270, "Hi", Color.RED, Color.BLACK, 2); } - + if (!ValueCheck.valueNoData(forecast.loTemp)) { g2d.setFont(font.deriveFont(26F)); @@ -296,4 +306,9 @@ public class DayForecastDisplay implements Display { public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) { } + + @Override + public String getDisplayName() { + return "7-day"; + } } diff --git a/src/com/flaremicro/visualforecast/displays/DayForecastDisplayOldAnimation.java b/src/com/flaremicro/visualforecast/displays/impl/SevenDayForecastDisplayOldAnimation.java similarity index 97% rename from src/com/flaremicro/visualforecast/displays/DayForecastDisplayOldAnimation.java rename to src/com/flaremicro/visualforecast/displays/impl/SevenDayForecastDisplayOldAnimation.java index ab88824..69f778c 100644 --- a/src/com/flaremicro/visualforecast/displays/DayForecastDisplayOldAnimation.java +++ b/src/com/flaremicro/visualforecast/displays/impl/SevenDayForecastDisplayOldAnimation.java @@ -1,4 +1,4 @@ -package com.flaremicro.visualforecast.displays; +package com.flaremicro.visualforecast.displays.impl; import static com.flaremicro.visualforecast.graphics.RenderConstants.MAINBAR_HEIGHT; @@ -16,6 +16,7 @@ import java.util.Locale; import com.flaremicro.visualforecast.RenderPanel; import com.flaremicro.visualforecast.api.ForecastProvider; +import com.flaremicro.visualforecast.displays.Display; import com.flaremicro.visualforecast.forecast.DayForecast; import com.flaremicro.visualforecast.forecast.ForecastDetails; import com.flaremicro.visualforecast.forecast.TownForecast; @@ -25,7 +26,7 @@ import com.flaremicro.visualforecast.graphics.FontManager; import com.flaremicro.visualforecast.graphics.RenderConstants; import com.flaremicro.visualforecast.icons.IconProvider; -public class DayForecastDisplayOldAnimation implements Display { +public class SevenDayForecastDisplayOldAnimation implements Display { private int dayOffset = 0; private Font font; private Font smallFont; @@ -39,7 +40,7 @@ public class DayForecastDisplayOldAnimation implements Display { private int ticksBeforeChange = 200; private int animationTicks = -1; - public DayForecastDisplayOldAnimation() { + public SevenDayForecastDisplayOldAnimation() { 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")); } @@ -263,4 +264,9 @@ public class DayForecastDisplayOldAnimation implements Display { @Override public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) { } + + @Override + public String getDisplayName() { + return "7-day-old"; + } } diff --git a/src/com/flaremicro/visualforecast/forecast/CurrentConditions.java b/src/com/flaremicro/visualforecast/forecast/CurrentConditions.java new file mode 100644 index 0000000..2e45d2c --- /dev/null +++ b/src/com/flaremicro/visualforecast/forecast/CurrentConditions.java @@ -0,0 +1,20 @@ +package com.flaremicro.visualforecast.forecast; + +import java.util.Date; + +public class CurrentConditions { + String station; + String stationCode; + Date timeObserved; + String condition; + byte icon; + byte temperature; + byte dewPoint; + short pressure; + short visibility; + float relativeHumidity; + short windSpeed; + short windGust; + float windBearing; + String windDirection; +} diff --git a/src/com/flaremicro/visualforecast/forecast/TownForecast.java b/src/com/flaremicro/visualforecast/forecast/TownForecast.java index 01adb88..2d3f7e1 100644 --- a/src/com/flaremicro/visualforecast/forecast/TownForecast.java +++ b/src/com/flaremicro/visualforecast/forecast/TownForecast.java @@ -6,17 +6,21 @@ import java.util.HashSet; import java.util.Set; public class TownForecast { + + private String townName; + private DayForecast[] dayForecast; + private Set displays = new HashSet(); + private HourlyForecast[] hourlyForecast; + private DetailedForecast[] detailedForecast; + public TownForecast(String townName, DayForecast[] dayForecast) { this.townName = townName; this.dayForecast = dayForecast; } - private final String townName; - private final DayForecast[] dayForecast; - private Set displays = new HashSet(); - - - private HourlyForecast[] hourlyForecast; + public void setDayForecast(DayForecast[] dayForecast){ + this.dayForecast = dayForecast; + } public boolean isDisplaySupported(String displayName) { @@ -47,4 +51,12 @@ public class TownForecast { public String getTownName() { return townName; } + + public DetailedForecast[] getDetailedForecast() { + return detailedForecast; + } + + public void setDetailedForecast(DetailedForecast[] detailedForecast) { + this.detailedForecast = detailedForecast; + } } diff --git a/src/com/flaremicro/visualforecast/icons/IconProvider.java b/src/com/flaremicro/visualforecast/icons/IconProvider.java index e7a66bb..1673fc7 100644 --- a/src/com/flaremicro/visualforecast/icons/IconProvider.java +++ b/src/com/flaremicro/visualforecast/icons/IconProvider.java @@ -53,7 +53,7 @@ public class IconProvider { public static final Icon BUTTER_RAIN = registerIcon(new BlizzardIcon(26, CLOUD, BUTTER)); public static final Icon RAIN_STORM = registerIcon(new LightningOverlay(27, SMALL_CLOUD, LIGHTNING_BOLT, RAIN_HEAVY)); - //public static final Icon INVALID_RAIN = registerIcon(new LightningOverlay(27, SUN, BUTTER, new BlizzardIcon(-1, LIGHTNING_BOLT, INVALID))); + public static final Icon INVALID_RAIN = registerIcon(new LightningOverlay(28, SUN, BUTTER, new BlizzardIcon(-1, LIGHTNING_BOLT, INVALID))); private static Icon registerIcon(Icon icon) { diff --git a/src/com/flaremicro/visualforecast/icons/impl/ButterIcon.java b/src/com/flaremicro/visualforecast/icons/impl/ButterIcon.java index 8de7abc..faa7c3c 100644 --- a/src/com/flaremicro/visualforecast/icons/impl/ButterIcon.java +++ b/src/com/flaremicro/visualforecast/icons/impl/ButterIcon.java @@ -21,6 +21,7 @@ public class ButterIcon extends Icon { }; Color[] iceShineAnimation = new Color[] { new Color(0xFFFFFF), + new Color(0xFFFFFF), }; public ButterIcon(int id) { diff --git a/src/com/flaremicro/visualforecast/icons/impl/InvalidIcon.java b/src/com/flaremicro/visualforecast/icons/impl/InvalidIcon.java index d089a0f..ced378d 100644 --- a/src/com/flaremicro/visualforecast/icons/impl/InvalidIcon.java +++ b/src/com/flaremicro/visualforecast/icons/impl/InvalidIcon.java @@ -19,6 +19,7 @@ public class InvalidIcon extends Icon { @Override public void drawIcon(Graphics2D g2d, float scale, int animationStep) { + g2d.getTransform(); g2d.setFont(fnt.deriveFont(0.8F)); g2d.translate(0.2F, 0.8F); DrawingUtil.drawOutlinedString(g2d, 0, 0, "X", Color.YELLOW, Color.BLACK, 1, 2/scale); diff --git a/vf1000.properties b/vf1000.properties index a6c66df..84d274b 100644 --- a/vf1000.properties +++ b/vf1000.properties @@ -1,3 +1,7 @@ #VisualForecast 1000 Properties file. Functional provider must be set for successful boot! -#Fri Mar 15 19:46:22 PDT 2024 +#Sat Nov 23 19:50:15 PST 2024 +announcement-dir=Announcements +display-selection=36-hour,7-day,hourly +music-dir=./Music +current-display-version=1 forecast-provider-jar=CanadaDatamartProvider.jar