From 5628a5b76e768eb1a1ae8b8804b0c5732f1693d7 Mon Sep 17 00:00:00 2001 From: Flare Microsystems Date: Fri, 8 Mar 2024 21:31:49 -0800 Subject: [PATCH] Added hourly forecast --- CanadaDatamartProvider.jar | Bin 13264 -> 13652 bytes CanadaDatamartProvider.properties | 4 +- MockForecastProvider.jar | Bin 3704 -> 4167 bytes .../visualforecast/RenderPanel.java | 82 +++--- .../visualforecast/VisualForecastFrame.java | 26 +- .../displays/HourlyForecastDisplay.java | 252 ++++++++++++++++++ .../visualforecast/forecast/DayForecast.java | 4 +- .../forecast/HourlyForecast.java | 24 ++ .../visualforecast/forecast/TownForecast.java | 17 +- .../graphics/RenderConstants.java | 2 +- vf1000.properties | 4 +- 11 files changed, 358 insertions(+), 57 deletions(-) create mode 100644 src/com/flaremicro/visualforecast/displays/HourlyForecastDisplay.java create mode 100644 src/com/flaremicro/visualforecast/forecast/HourlyForecast.java diff --git a/CanadaDatamartProvider.jar b/CanadaDatamartProvider.jar index b4a6838e8d30349d3ee8e8afa1092d21b43ec0b0..d793fc99b48603e972a88440a22fc2738abe9147 100644 GIT binary patch delta 8600 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 Vjq(58#bE`r@=zjtXaCRX{{v?x$kPA- diff --git a/CanadaDatamartProvider.properties b/CanadaDatamartProvider.properties index 0da62c2..21f75b6 100644 --- a/CanadaDatamartProvider.properties +++ b/CanadaDatamartProvider.properties @@ -1,4 +1,4 @@ #VisualForecast 1000 Properties file. Functional provider must be set for successful boot! -#Thu Mar 07 16:27:03 PST 2024 +#Fri Mar 08 16:38:56 PST 2024 towns-by-code= -towns-by-name-and-province=Vancouver,BC;Kamloops,BC;Kelowna,BC +towns-by-name-and-province=Duncan,BC;Halifax,NS;Courtenay,BC;Comox,BC diff --git a/MockForecastProvider.jar b/MockForecastProvider.jar index d6144df5f398dae5281bfedd1dbc5022f4f103be..08e10bea9e23e700a98489dca12930b3e21b9883 100644 GIT binary patch delta 3524 zcmV;#4LkDq9LFFHP)h>@6aWYa2mo26Xps$G168DGk#1IhrB@4lQ`H&&pXPNFZc7Ml zp%oAiC4ES-j#^qo`=o);c1>EA!mPK+Esdl}Om14r++>c;`N9{zrb9(He9bAcmcd}| z?c786e!4mLem~sQ{kG}8@7~)a6jZG3FS#fGbH3;Kf8ROx=~oXQ18|O5=|F+N1>wX< z%}`89sUy*Ua4KO8wb7ceJX@R+${g)`CN=;0OZ>dpSQ;IAnb98apGO*gvjmiMSI2Wio8AJ8+sn-OSu} zVj)gS?CgdA=5`}+HvdRhf4r|0fD02F`R~nSl3H zWn`Rxh2;VT(TIR(mQcaAW6>QulvKopa#YEv#@UpgHRdMF^ERKj>HQUb9CM9~mF&H( z#oyK2DxsF-T4ISzWSnQ;A!8NK7V5L10plUzJlfMfH8sxWR-Tl88|Z2BbxOE^f@x2w>JFV7O=PEkM~TK+qD4k4OU(BB)^!9sStJnb>e(ov zohTC=&cq|kpAL#8pe0fxEVEw52A1*UWTtjW!bTQbo?Y7|qg(f=yQwGW&&Aq98R=G1 zT1?MKP)0AWva-7jY?ARVU5tT&j<%*gUt1t3p`Wz3ZP#cwb#85u@orw`$}S_-1LSLe zhpLR~niUy?xfQy@5@?HU{^-_WjaLlG*qSq?uh30J$y95K2oTdvZIcn>WlnurptEa} zggAK|h$qH)J}Ki;o-fkp`F|7$t>) zu%c;dN{vX^PBsI>i7_>mX2BgY-ot`_rCGsXM{j2`TJ4>g zRzAY)Dcv#N<`bNyUOYsFT0isj9}zfr2A*+lkIFcP&yrteZd;Y{T*SV&mD)U2l-a}h z98>x8xed#2>oZbX(Z>;dQO1|>Wq}eif{sKc70V04|F(iSUYj1rQ!>7Pil+tU5JRRL zYdm$1Ow-IPDbR+fT4u&FI?Sn&3!ekezUe*hWZC3${kDwn;JehCmYUA6lI~Vh;b=0dDOxl^=alH@NPaKl5BMXUIUGrQ zETL%nWwPDc{1k{Y1rbX0su_`v0vL`4)sZ9(VhLkl)%1rvW?TsUMl|_9>0VTr)E#Aa zRZgv-dq=^Tc9OzB^{cX#uV^;te~xEe_%B{{;D5*6lY_%4Rf))dc#SN=mX4_^JM3Lg z#Ul!Y)gdebi*n0p*VR-ilcck&ZF^Wva#Ces<0EKxl6FK3Xi9inFr|d)%o6lj?0;in z@^aQzRmq%eh%P?%h{|y}1l{dd&8V7OVvd;W5FVmbuJ&7$ zm>Q2LDOnVY62mKhUp%eRy90$$O2^-cOB-3yJXy>aW#k;yJEhR;^KtIxh|^@TKrEzc zAw|LH2%q7{DQQ(Sl@t_-)2VF4VuAVI>9ftvf%axY+frGap<7WRbQnlO*_Kj2(~d&A z=tdz>e6qlZ1H-hOs50FrDw?rqJQ7H%D!(BFXg>_*l2;Lbb*wuPW%jxPBpp`UqkMNM zJK0TR1?$BUVx5K9SwK}w?^rY{=Nk~Xp-9vhxP#B4>6>Xxf8u57DCCgEQxphUJ?=or z=J5nVc2992fwnH{$Udpxc!1Wb~a=O5LV{0HYTg4!KSFKE^^* zmfTJQ-OT7kS=42q7c&~pqO%NCWpvooDjV1(x+Twuxw6ne6O0yR<%qV zblgBMGf}sJzK_un)7BgVdp~2ljGVeX2KFJwt}?NIxdwI(W4leP*uZXJ>}Jm`W}Zq6 z^fpF6;<-ylpTOS7b&A|W-&fG0lVgYQY0~fF%du(aO7e%RZPfwHKXw#BBEf;48Zd#Dc10_rCUAo(tuApLFYO^*M56&*3b9)|A_$$?bg=`MtZ#1%! zRR{h~BOBQa@I8x0A@c4Yc%F1@A%9<_k%PSO;h*>yX^W!~FX3hITj?uVmTxwHi8{L& z|2~BO?1$v9nh@e~o!NFcMS+=)Qt-7SL)a*(7$XJaD5976DW-Bw79WHq%2F-yp%Y_%y{V0~no~YISMUnr1kZ^CTcFUFtQCjUTG#*9#u&mvWZPgQ^yuq4BTYIIu zn8r8PIkLPfAxt9dVz-?ZIFF;QtIVZSw`$=LQ4}g8YL?hbh?*tNNwFwU?RHrw#FAYW zv5+}>OCCqtF^9gdqnLJ+zt_{R8;G?xQg^(Gy5SzG;agFM+o-Z{M+feIAhzBK6?Y+q zz0`N_##OZLCdx#PhkLR-+%1-gGxZw3TAU@8lf@;tRA;1x^bQEGsG!Y?QAak|S4TW# zM%u~RdQmB=hN(%r0`W65H zP)h>@6aWYa2mn>2XjlM~TnbHp+iue^82;R(D=mQ?V2q{=cDPxiK{SLA(k3p3GzqD| zq(PB(=epkNk;aqjR^pBq;xM3^#03wqheG^zqwWH@AyVwm@pp23@$1J=09#nEpv3T4 z=ze;XaU=Um7(Ib@l#bM3$g?ADq~HUa_O*DIzLnheqymh2jmnR=i_M2*(&K}DX@ojemRqHB(jJo0j>?sN z%CNMt`=|V{*=7iz>8`ASEFwghXK4P7`VaAJi{f7n`yDzD?_|=o)PiSiZj@UWA4A(y z1BNH9|NBkbH3V34^=>nN1RKqEmFmV3%9wHJPJ{}sICM8cb%ItR)NqxdcA$qw$UWt1 z)L)SCUXikI^hkB3dEicl719KBp&`9w3-^$zpR2`8hBTIl8Q~g@*J<^J*iKVT8k=nS z9J6Phvf$|@8b6Zw6K)VnCPduCVqxoom`5(E(rq7|Y3GIL5up%-C1|Oi5qJ>x}eYDf=7h`0hJAnmA26#M2J(v_tF<9C+l~gtWiv z6V`qMP)i30%^LM=!;^Ikl>=F%Xp;>MLk?A>Xjt5tW5!Ag008@6aWYa2mlzUW|0kE11zRyk#1Ihtyc+n6y+Iy|74HJGD((& z06{LXN)AedYKRF}PO`EjVRsWupvKAWBpKN3th2KTL0hR>duVN~_OJ(4u*IuZjwTce zwI|lv`?9yShrN%-R;_Kd-#0Va4M_V0(&X8hf8PJQ{`ddB|9Il%V9p3DP`9dzImkL! zYzv)3{Ek|5G^LU?X-zDlB{g%MKz>BLkE>pP6bksybS|No0_;+fF+DS^8WLs- zcpEZCQt2C&FpG?BQic+`o=Qt75%6qM6M9mSFqhh)QPb3u1rR8e;fBYH3k0gqFYE#= z#9}WN3Diu@fELq}>8c<-Cy17@1Q$}k4WVF9Pkp#aVAT{k%-O0dz(u&&i`NKTdak-M zF2OQ?fjliPAQ~i;b1VsM_in|A`!FAsGM3}D#M>HYa^{vbygC_r%Db40DjApZXxxpV z_Rb~=t4Oagp=aWw+h12eUlLZ+Tz9F)D7(9Y-PH<|pUumE^}9yKTFY`v zxVgC}*tW4ZTpw(cu$~6fVyNnFD`)D-Pgv1^lC04vqlq<&L&1%$(Kc3zMBBrgCA3f~ zMF%sjU{60#t`dVDPt4s1adkPvnF9Pt1ZjQw#(?SBI>9QM?<->hKZ35#V`{V zBT*ThEal>G8Q3c0Doc%l-qz;&u3&Q{Dxrt0H}5iOR;`@dF5~qq=F5ta>0XMpRaJ(6 zEz63GzMO;=umqZ7cSsu;G+Clw#z4-MC1JVJ$W@a;36QW{?Ua#Vu>wmh($>CJLXskm zB=r&QPszBJ`-`mpuKKpd_Rg;6Fn6V8nB3)$G}cF>&EclrNNfAn=5R#9Fd2-*6w_1< zH7;Qn`HT$eBdU>R#oaQlW5qdH#b|4PXIm3#@)VK!8)#k~vMq%hWbCnc6fMDBcgT1*cg<+% zOZXtg+L=r%36n?qVeZNBxOoMC`iKlK zB+f!DskUW?`e<2EXhG#1(_>1aOEEP5wm={9v7gJsNAAo)jn?J*b6IZBwq4M=JImPy zCU?^oQdT}i+u6p1a+7Kjap^iQ9++6VGp3fP3MWox_O0AN!eyZ|L#Qi%pXxT1ZA`XV$DR+%ID${o%%xTHbcgk2)3eT7pU1EQ z4-&C-E7I)8W2J8O<@V<^MwcB$LGaF?^Ow;B&c& zoxB}P%QzFCXZBNKPHzHfAEh-^1ig4%p!WO&;!1f!##itpt&T}`ml;fd5~;4TV0qAW z!()ICr|@+q;~N5%Wep8e+Av$nyDa4b+H1cp<2$_fd-yaEj5G8-8Q;fKw6f7rOkJ7H zzsVL@?1wUbloeaW$WLVa6hEVSA5_vEsu9ytnyHwYPFscO;gS4Y#xwW@E&Du@mV~aD z);X`m)$lkdk@Dh1{Mu=M%^wY9P>ZTVDQYBiyWujempo#h*+TZHCV$cqr7&d$%welc zv7jSB-Uu~n&i^#);?t5F*5Bd{KKu>Od-3lmuGz#1}UgLMq93v6&% zpw|W)7;Fw~v_Z)RgO-y($Oiq6ejB4(CXD(W0})0y*a7(+{VvA3Cp`HJY;+r=S7%Y5 zjb6iOEQ`*tQI*j_$Es{&J1kFuAxE;%Ms-Guvie0fYA~9A35+;sv5k(}==Bcjx6wB; zI^_78X=86<>}H!&f566WVeD-VHp|9tW$bnbn{8w7V(iYqdmNrhZ1jDMejxB63q6dz z2dxyjhn_dmbqFY?RPj?{%%o=kC74BNGn)=q#nd|&%P;QT zQ7p!jB=rn`rQVBJDvEHCSV|Y88eA;eaEXZ1g0~xG;&!^|>_deZL#22E%f-`l$9azK zhtH!5_gc~Lsfep4km$~`2_2In8g{oUhu zaMN)-MDLG>Dl3lSkue;qd^Bq@02e(kqw2Vv2478oLtSlIpF{l;^^RejzWfx}QGAN* z`}pwV_!*^mxY{ZYVcy9TI2OuZdjO@C3y$L$kv?z1DsuPfaXc2eIZrI8JbCXc&rWhY z2fSRZAt!55i1ozbT9l*Sa=yei>o}L_w)uH{!E(MBU&NQlf{)Jub{JwWefdc4h@YzY zloiB(eHH#0WB9V)caI&_CLYL_DOty^bz$y3sJg}MinG}HW42o%87QGk`6Rt z3!xE0qJ(r(>ne1ioBn&S9oujXUD1-b8X5HBdiuJFEZ&MZ?xJhg17wqG*y1*2P2CZP zTMr(=ukdSPQo@4{x2s{`S<3o+^4X8yP|HPLz4$G)+~hOD+c>qlDXQP$DYCJhYUB5R z)bf(wApU?qlC>o2@F)BkeDC;6Hm|oisaZT5e?5xl4nPW3j^Q5%tz7ny@Jpwq$F+nR zgr>JnYiGWX!h0F7aKVs~i5ghp6p-tv5IK_V`nhgW{kR+}LgWjVqr2SE z&2v3`hUT70nt54GcXoJ{RvFXp%#yt+Ws;)ED)I)EC%pdwP)i30;al!Rc?kdjloJ2| zP)h>@6aWYa2mmamW|J!nPk+yD(=Z(V+@vclfw7G-nljkNWsNqXA%u{II1FhLQh`Z> zBJJk7-s+LYlj~OE#w+l5dkqfNBn~_P4~6*Ijk*JHAyVwm@%PX1&tKnv0NBFa3Q7zQ zh3=<^88@=8gwYddN9jlnhCDmeMhZT#X;Hb!b`1fRTz|cr48eM{U8TBlgfeCvx)q^6Y3{j`VTCjSU1&%z*}^?!>gQ@PlOc^IVn(<^<5gO{CbrX5lg0*H zKF91gPnq}h5{(~7{1FR;k_i#lu~^u;Am)*aDtY8W0v|C~L{Ge@oifdFa*i8GV~l#T zF-9ZV9Ai0I49B>0ks15ypD5`wd3_=MSIRy`9cRA7gNf6$Lp<#ePdmi^z=21uO-TEz zK4I-QP)i309fOMx#gjx1l>->4W|Q0wLk=vaW?11{?nHSB005K|lPwQrAS|Y4SRI3l y55)lh0QLd^06YKy00000000000000@3X?w%EtB65I|6(RlN=Bw2L22H0002!(9pvG diff --git a/src/com/flaremicro/visualforecast/RenderPanel.java b/src/com/flaremicro/visualforecast/RenderPanel.java index 37ecee8..3834f14 100644 --- a/src/com/flaremicro/visualforecast/RenderPanel.java +++ b/src/com/flaremicro/visualforecast/RenderPanel.java @@ -29,6 +29,7 @@ import com.flaremicro.visualforecast.api.ForecastProvider; import com.flaremicro.visualforecast.displays.BootupDisplay; import com.flaremicro.visualforecast.displays.DayForecastDisplay; import com.flaremicro.visualforecast.displays.Display; +import com.flaremicro.visualforecast.displays.HourlyForecastDisplay; import com.flaremicro.visualforecast.forecast.ForecastDetails; import com.flaremicro.visualforecast.graphics.DrawingUtil; import com.flaremicro.visualforecast.graphics.FontManager; @@ -54,6 +55,8 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener { private Rectangle exclusiveRedrawBound = null; private Rectangle crawlBound = null; + private Rectangle currentBound = new Rectangle(0, 0, 0, 0); + private String currentTown = ""; private String currentForecast = ""; @@ -109,30 +112,8 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener { public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = prepareFrameBuffer(); - - - if(g.getClipBounds().equals(this.crawlBound)) - { - 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; - } - drawMainRegion(g2d); - + if (currentFlavour != null) { if (this.getBounds().equals(g.getClipBounds())) @@ -152,7 +133,7 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener { 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.setPaint(new GradientPaint(0, HEADERBAR_Y, BG_ORANGE, 0, HEADERBAR_Y + (HEADERBAR_HEIGHT + 10), BG_PURPLE)); g2d.shear(HEADERBAR_SHEAR, 0); g2d.fillRect(-HEADERBAR_OFFSET, HEADERBAR_Y, HEADERBAR_WIDTH, HEADERBAR_HEIGHT); @@ -160,7 +141,7 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener { 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.setPaint(new GradientPaint(0, TOPBAR_HEIGHT, BG_PURPLE, 0, MAINBAR_HEIGHT, BG_ORANGE)); g2d.fillRect(0, TOPBAR_HEIGHT, W, MAINBAR_HEIGHT); g2d.fillRect(0, TOPBAR_HEIGHT, W, MAINBAR_HEIGHT); @@ -177,7 +158,7 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener { 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); - + g2d.setColor(BG_BLUE); g2d.fillRect(0, H - INFOBAR_HEIGHT, W, INFOBAR_HEIGHT); @@ -202,7 +183,7 @@ 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); + requestRepaint(this.redrawBound); } } if (this.currentFlavour != null) @@ -218,10 +199,37 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener { this.currentCrawlStringWidth = g.getFontMetrics(font.deriveFont(26F)).stringWidth(currentCrawlString); g.dispose(); } - else if (this.currentCrawlString != null) + } + + public void requestFullRepaint() { + currentBound = this.getBounds(); + } + + + public void requestRepaint(Rectangle bound) { + if(currentBound.width == 0) + currentBound = new Rectangle(bound); + else currentBound.add(bound); + } + + public void requestBoundedRepaint() { + requestRepaint(this.redrawBound); + } + + public void requestExclusiveBoundedRepaint() { + requestRepaint(exclusiveRedrawBound); + } + + public void performPaintIfNeeded() { + if (this.currentCrawlString != null) { - this.crawlPosition-=2; - repaint(0, this.crawlBound.x, this.crawlBound.y, this.crawlBound.width, this.crawlBound.height); + this.crawlPosition -= 2; + requestRepaint(crawlBound); + } + if(this.currentBound.width != 0) + { + repaint(currentBound); + currentBound.width = 0; } } @@ -293,7 +301,7 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener { } public void nextDisplay() { - this.currentFlavour = new DayForecastDisplay(); + this.currentFlavour = new HourlyForecastDisplay(); this.currentFlavour.initDisplay(this, forecastProvider, ticks, iconAnimationTicks); this.loseRedrawRegion(); this.requestFullRepaint(); @@ -307,18 +315,6 @@ public class RenderPanel extends JPanel implements Tickable, ComponentListener { this.currentForecast = currentForecast; } - public void requestFullRepaint() { - repaint(); - } - - public void requestBoundedRepaint() { - repaint(redrawBound); - } - - public void requestExclusiveBoundedRepaint() { - repaint(exclusiveRedrawBound); - } - private void loadCrawlStrings() { File crawl = new File("./crawl.txt"); ArrayList strings = new ArrayList(); diff --git a/src/com/flaremicro/visualforecast/VisualForecastFrame.java b/src/com/flaremicro/visualforecast/VisualForecastFrame.java index a12df52..b2bd384 100644 --- a/src/com/flaremicro/visualforecast/VisualForecastFrame.java +++ b/src/com/flaremicro/visualforecast/VisualForecastFrame.java @@ -2,6 +2,8 @@ package com.flaremicro.visualforecast; import java.awt.BorderLayout; import java.awt.EventQueue; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.event.WindowEvent; @@ -9,6 +11,7 @@ import java.awt.event.WindowListener; import java.io.File; import javax.swing.JFrame; +import javax.swing.Timer; import com.flaremicro.visualforecast.api.ForecastProvider; import com.flaremicro.visualforecast.api.ForecastProviderManager; @@ -23,6 +26,8 @@ public class VisualForecastFrame extends JFrame implements WindowListener, KeyLi private ForecastProviderManager forecastProviderManager; private Executor executor; private PropertyManager propertyManager = new PropertyManager(); + private Timer timer; + private Timer timer2; private boolean isFullscreen = false; /** @@ -37,7 +42,7 @@ public class VisualForecastFrame extends JFrame implements WindowListener, KeyLi frame.setVisible(true); frame.init(); //GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()[1].setFullScreenWindow(frame); - frame.createBufferStrategy(2); + //frame.createBufferStrategy(2); } catch (Exception e) { @@ -50,6 +55,10 @@ public class VisualForecastFrame extends JFrame implements WindowListener, KeyLi public void end() { if (executor != null) executor.end(); + if (timer != null) + { + timer.stop(); + } if (forecastProviderManager != null) forecastProviderManager.end(); propertyManager.store(); @@ -58,6 +67,14 @@ public class VisualForecastFrame extends JFrame implements WindowListener, KeyLi public void init() { executor = new Executor(this.renderPane, 30); executor.begin(); + timer = new Timer(33, new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + renderPane.performPaintIfNeeded(); + } + }); + timer.start(); + new Thread() { public void run() { @@ -67,6 +84,7 @@ public class VisualForecastFrame extends JFrame implements WindowListener, KeyLi propertyManager.store(); ForecastProvider provider = forecastProviderManager.loadProvider(new File(forecastProvider)); renderPane.setForecastProvider(provider); + } }.start(); @@ -79,9 +97,9 @@ public class VisualForecastFrame extends JFrame implements WindowListener, KeyLi setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); setBounds(100, 100, 640 * 2, 480 * 2); renderPane = new RenderPanel(propertyManager); - renderPane.setBorder(null); - renderPane.setLayout(new BorderLayout(0, 0)); - setContentPane(renderPane); + //renderPane.setBorder(null); + //renderPane.setLayout(new BorderLayout(0, 0)); + add(renderPane); setUndecorated(true); addWindowListener(this); addKeyListener(this); diff --git a/src/com/flaremicro/visualforecast/displays/HourlyForecastDisplay.java b/src/com/flaremicro/visualforecast/displays/HourlyForecastDisplay.java new file mode 100644 index 0000000..7940630 --- /dev/null +++ b/src/com/flaremicro/visualforecast/displays/HourlyForecastDisplay.java @@ -0,0 +1,252 @@ +package com.flaremicro.visualforecast.displays; + +import static com.flaremicro.visualforecast.graphics.RenderConstants.BG_BLUE; +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.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.forecast.ForecastDetails; +import com.flaremicro.visualforecast.forecast.HourlyForecast; +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 HourlyForecastDisplay implements Display { + private int dayOffset = 0; + private Font font; + private Font smallFont; + private ForecastDetails details; + private TownForecast currentTown = null; + private int townIndex; + + private int ticksBeforeChange = 200; + private int animationTicks = -1; + + DateFormat simpleDateFormat = new SimpleDateFormat("ha"); + + public HourlyForecastDisplay() { + 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) { + + } + + @Override + public void initDisplay(RenderPanel renderer, ForecastProvider forecastProvider, long ticks, int iconTicks) { + this.details = forecastProvider != null ? forecastProvider.getForecast() : null; + renderer.setCurrentForecast("12 Hour 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); + } + + @Override + public void drawDisplay(RenderPanel renderer, Graphics2D g2d, long ticks, int iconTicks) { + } + + public int minTemp(HourlyForecast[] forecast) { + int min = Integer.MAX_VALUE; + for (int i = 0; i < forecast.length; i++) + { + int currMin; + if (ValueCheck.valueNoData(forecast[i].dewPoint) && ValueCheck.valueNoData(forecast[i].temp)) + continue; + else if (ValueCheck.valueNoData(forecast[i].dewPoint)) + currMin = forecast[i].temp; + else if (ValueCheck.valueNoData(forecast[i].temp)) + currMin = forecast[i].dewPoint; + else currMin = Math.min(forecast[i].temp, forecast[i].dewPoint); + if (currMin < min) + min = currMin; + } + return min; + } + + public int maxTemp(HourlyForecast[] forecast) { + int max = Integer.MIN_VALUE; + for (int i = 0; i < forecast.length; i++) + { + int currMax; + if (ValueCheck.valueNoData(forecast[i].dewPoint) && ValueCheck.valueNoData(forecast[i].temp)) + continue; + else if (ValueCheck.valueNoData(forecast[i].dewPoint)) + currMax = forecast[i].temp; + else if (ValueCheck.valueNoData(forecast[i].temp)) + currMax = forecast[i].dewPoint; + else currMax = Math.max(forecast[i].temp, forecast[i].dewPoint); + if (currMax > max) + max = currMax; + } + return max; + } + + @Override + public void drawBoundLimitedDisplay(RenderPanel renderer, Graphics2D g2d, Rectangle bounds, long ticks, int iconTicks) { + HourlyForecast[] forecast = currentTown.getHourlyForecast(); + if(forecast == null) + return; + + g2d.setColor(RenderConstants.BG_BLUE); + //g2d.fillRect(RenderConstants.SIDE_OFFSET, RenderConstants.TOPBAR_HEIGHT + 20, RenderConstants.W - RenderConstants.SIDE_OFFSET * 2, RenderConstants.MAINBAR_HEIGHT - 40); + + DrawingUtil.drawGradientRect(g2d, RenderConstants.SIDE_OFFSET, RenderConstants.TOPBAR_HEIGHT + 20, RenderConstants.W - RenderConstants.SIDE_OFFSET * 2, RenderConstants.MAINBAR_HEIGHT - 40, 15, BG_BLUE.darker(), BG_BLUE.brighter()); + + int min = minTemp(forecast); + int max = maxTemp(forecast); + + float range = Math.abs(min)+Math.abs(max); + + + + g2d.setPaint(new GradientPaint(0, RenderConstants.TOPBAR_HEIGHT + 40, RenderConstants.BG_ORANGE, 0, RenderConstants.MAINBAR_HEIGHT, RenderConstants.BG_PURPLE)); + g2d.fillRect(RenderConstants.SIDE_OFFSET + 40, RenderConstants.TOPBAR_HEIGHT + 40, RenderConstants.W - RenderConstants.SIDE_OFFSET * 2 - 60, RenderConstants.MAINBAR_HEIGHT - 124); + + g2d.setColor(Color.BLACK); + g2d.drawRect(RenderConstants.SIDE_OFFSET, RenderConstants.TOPBAR_HEIGHT + 20, RenderConstants.W - RenderConstants.SIDE_OFFSET * 2, RenderConstants.MAINBAR_HEIGHT - 40); + + /*float lineHeight = (RenderConstants.MAINBAR_HEIGHT - 104) / 9F; + for(int i = 0; i < 10; i++) + { + g2d.drawLine(RenderConstants.SIDE_OFFSET + 36, (int)(RenderConstants.TOPBAR_HEIGHT + 40 + lineHeight * i), RenderConstants.W - RenderConstants.SIDE_OFFSET - 36, (int) (RenderConstants.TOPBAR_HEIGHT + 40 + lineHeight * i)); + }*/ + g2d.setFont(smallFont.deriveFont(20F)); + FontMetrics fm = g2d.getFontMetrics(); + + 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, 410, RenderConstants.TOPBAR_HEIGHT + 35, "Precipitation%", Color.CYAN, Color.BLACK, 2); + + + String minText = min + "\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+40-fm.stringWidth(minText), RenderConstants.TOPBAR_HEIGHT + MAINBAR_HEIGHT - 92, minText, Color.YELLOW, Color.BLACK, 2); + + int slotWidth = (RenderConstants.W - RenderConstants.SIDE_OFFSET * 2 - 60) / 12; + + int lastDewpoint = 0; + int lastTemperature = 0; + int lastPercip = 0; + + 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.setColor(RenderConstants.BG_PURPLE.brighter()); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40, RenderConstants.TOPBAR_HEIGHT + 50 + RenderConstants.MAINBAR_HEIGHT - 144, (RenderConstants.W - RenderConstants.SIDE_OFFSET - 20), RenderConstants.TOPBAR_HEIGHT + 50 + RenderConstants.MAINBAR_HEIGHT - 144); + + //BlackLines + g2d.setClip(RenderConstants.SIDE_OFFSET + 40, RenderConstants.TOPBAR_HEIGHT + 40, RenderConstants.W - RenderConstants.SIDE_OFFSET * 2 - 60, RenderConstants.MAINBAR_HEIGHT - 124); + g2d.setStroke(new BasicStroke(2)); + g2d.setColor(Color.BLACK); + for(int i = 0; i < Math.min(12, forecast.length); i++) + { + int nextDewpoint = (RenderConstants.TOPBAR_HEIGHT + 50) + (RenderConstants.MAINBAR_HEIGHT - 144) - (int)(((max-forecast[i].dewPoint)/range)*(RenderConstants.MAINBAR_HEIGHT - 144)); + int nextTemperature = (RenderConstants.TOPBAR_HEIGHT + 50) + (RenderConstants.MAINBAR_HEIGHT - 144) - (int)(((max-forecast[i].temp)/range)*(RenderConstants.MAINBAR_HEIGHT - 144)); + int nextPercip = (RenderConstants.TOPBAR_HEIGHT + 50) + (RenderConstants.MAINBAR_HEIGHT - 144) - (int) ((forecast[i].percip/100F)*(RenderConstants.MAINBAR_HEIGHT - 144)); + if(i == 0) + { + lastDewpoint = nextDewpoint; + lastTemperature = nextTemperature; + lastPercip = nextPercip; + } + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i-1))+1, lastDewpoint+2, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*i)+2, nextDewpoint+2); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i-1))+1, lastPercip+2, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*i)+2, nextPercip+2); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i-1))+1, lastTemperature+2, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*i)+2, nextTemperature+2); + if(i == Math.min(12, forecast.length)-1) + { + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i)), nextDewpoint+2, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i+2)), nextDewpoint+2); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i)), nextPercip+2, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i+2)), nextPercip+2); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i)), nextTemperature+2, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i+2)), nextTemperature+2); + } + lastPercip = nextPercip; + lastTemperature = nextTemperature; + lastDewpoint = nextDewpoint; + } + g2d.setClip(null); + + for(int i = 0; i < Math.min(12, forecast.length); i++) + { + g2d.setClip(RenderConstants.SIDE_OFFSET + 40, RenderConstants.TOPBAR_HEIGHT + 40, RenderConstants.W - RenderConstants.SIDE_OFFSET * 2 - 60, RenderConstants.MAINBAR_HEIGHT - 124); + int nextDewpoint = (RenderConstants.TOPBAR_HEIGHT + 50) + (RenderConstants.MAINBAR_HEIGHT - 144) - (int)(((max-forecast[i].dewPoint)/range)*(RenderConstants.MAINBAR_HEIGHT - 144)); + int nextTemperature = (RenderConstants.TOPBAR_HEIGHT + 50) + (RenderConstants.MAINBAR_HEIGHT - 144) - (int)(((max-forecast[i].temp)/range)*(RenderConstants.MAINBAR_HEIGHT - 144)); + int nextPercip = (RenderConstants.TOPBAR_HEIGHT + 50) + (RenderConstants.MAINBAR_HEIGHT - 144) - (int) ((forecast[i].percip/100F)*(RenderConstants.MAINBAR_HEIGHT - 144)); + if(i == 0) + { + lastDewpoint = nextDewpoint; + lastTemperature = nextTemperature; + lastPercip = nextPercip; + } + g2d.setStroke(new BasicStroke(2)); + g2d.setColor(Color.WHITE); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i-1)), lastDewpoint, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*i), nextDewpoint); + g2d.setColor(Color.CYAN); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i-1)), lastPercip, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*i), nextPercip); + g2d.setColor(Color.RED); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i-1)), lastTemperature, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*i), nextTemperature); + if(i == Math.min(12, forecast.length)-1) + { + g2d.setColor(Color.WHITE); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i)), nextDewpoint, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i+1)), nextDewpoint); + g2d.setColor(Color.CYAN); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i)), nextPercip, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i+1)), nextPercip); + g2d.setColor(Color.RED); + g2d.drawLine(RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i)), nextTemperature, RenderConstants.SIDE_OFFSET+40+slotWidth/2+(slotWidth*(i+1)), nextTemperature); + } + + g2d.setClip(null); + lastPercip = nextPercip; + lastTemperature = nextTemperature; + lastDewpoint = nextDewpoint; + + String timeString = simpleDateFormat.format(forecast[i].hour); + 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); + 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); + + IconProvider.drawIcon(g2d, IconProvider.INDEXED_ICONS[forecast[i].iconId], RenderConstants.SIDE_OFFSET + 45 + i * slotWidth , RenderConstants.TOPBAR_HEIGHT + MAINBAR_HEIGHT - 55, slotWidth - 10, iconTicks); + } + g2d.setStroke(new BasicStroke(2)); + g2d.setColor(Color.BLACK); + g2d.drawRect(RenderConstants.SIDE_OFFSET + 40, RenderConstants.TOPBAR_HEIGHT + 40, RenderConstants.W - RenderConstants.SIDE_OFFSET * 2 - 60, RenderConstants.MAINBAR_HEIGHT - 124); + + } + + @Override + public void redrawRegionlost(RenderPanel renderer) { + renderer.addRedrawBound(0, RenderConstants.TOPBAR_HEIGHT, RenderConstants.W, RenderConstants.MAINBAR_HEIGHT); + } + + @Override + public void notifyForecastProviderUpdate(RenderPanel renderer, ForecastProvider forecastProvider) { + + } +} diff --git a/src/com/flaremicro/visualforecast/forecast/DayForecast.java b/src/com/flaremicro/visualforecast/forecast/DayForecast.java index 5a68f71..ab3c612 100644 --- a/src/com/flaremicro/visualforecast/forecast/DayForecast.java +++ b/src/com/flaremicro/visualforecast/forecast/DayForecast.java @@ -1,5 +1,7 @@ package com.flaremicro.visualforecast.forecast; +import com.flaremicro.visualforecast.icons.IconProvider; + public class DayForecast { public byte hiTemp; public byte loTemp; @@ -11,7 +13,7 @@ public class DayForecast { public DayForecast(byte hiTemp, byte loTemp, byte iconId, String weatherLine1, String weatherLine2, float percipPercent){ this.hiTemp = hiTemp; this.loTemp = loTemp; - this.iconId = (byte)(iconId & 63); + this.iconId = (byte)(iconId % IconProvider.INDEXED_ICONS.length); this.weatherLine1 = weatherLine1; this.weatherLine2 = weatherLine2; this.percipPercent = percipPercent; diff --git a/src/com/flaremicro/visualforecast/forecast/HourlyForecast.java b/src/com/flaremicro/visualforecast/forecast/HourlyForecast.java new file mode 100644 index 0000000..43f8f26 --- /dev/null +++ b/src/com/flaremicro/visualforecast/forecast/HourlyForecast.java @@ -0,0 +1,24 @@ +package com.flaremicro.visualforecast.forecast; + +import java.util.Date; + +import com.flaremicro.visualforecast.icons.IconProvider; + +public class HourlyForecast { + public final Date hour; + public final byte iconId; + public final byte temp; + public final short windSpeed; + public final float percip; + public final byte dewPoint; + + public HourlyForecast(Date hour, byte iconId, byte temp, short windSpeed, float percip, byte dewPoint) + { + this.hour = hour; + this.iconId = (byte) (iconId % IconProvider.INDEXED_ICONS.length); + this.temp = temp; + this.windSpeed = windSpeed; + this.percip = percip; + this.dewPoint = dewPoint; + } +} diff --git a/src/com/flaremicro/visualforecast/forecast/TownForecast.java b/src/com/flaremicro/visualforecast/forecast/TownForecast.java index 553ff45..49d31af 100644 --- a/src/com/flaremicro/visualforecast/forecast/TownForecast.java +++ b/src/com/flaremicro/visualforecast/forecast/TownForecast.java @@ -1,18 +1,27 @@ package com.flaremicro.visualforecast.forecast; public class TownForecast { - public TownForecast(String townName, DayForecast[] dayForecast){ + public TownForecast(String townName, DayForecast[] dayForecast) { this.townName = townName; this.dayForecast = dayForecast; } - + private final String townName; private final DayForecast[] dayForecast; - + private HourlyForecast[] hourlyForecast; + + public void setHourlyForecast(HourlyForecast[] forecast) { + this.hourlyForecast = forecast; + } + + public HourlyForecast[] getHourlyForecast() { + return this.hourlyForecast; + } + public DayForecast[] getDayForecast() { return dayForecast; } - + public String getTownName() { return townName; } diff --git a/src/com/flaremicro/visualforecast/graphics/RenderConstants.java b/src/com/flaremicro/visualforecast/graphics/RenderConstants.java index 4e033d8..828faeb 100644 --- a/src/com/flaremicro/visualforecast/graphics/RenderConstants.java +++ b/src/com/flaremicro/visualforecast/graphics/RenderConstants.java @@ -31,6 +31,6 @@ public class RenderConstants { public static final Color BG_PURPLE = new Color(0x2b29b3); - public static final Color BG_OORANGE = new Color(0xff8c00); + public static final Color BG_ORANGE = new Color(0xff8c00); public static final Color BG_BLUE = new Color(0x394aa8); } diff --git a/vf1000.properties b/vf1000.properties index 871d714..0c82524 100644 --- a/vf1000.properties +++ b/vf1000.properties @@ -1,3 +1,3 @@ #VisualForecast 1000 Properties file. Functional provider must be set for successful boot! -#Thu Mar 07 16:27:03 PST 2024 -forecast-provider-jar=CanadaDatamartProvider.jar +#Fri Mar 08 21:30:25 PST 2024 +forecast-provider-jar=MockForecastProvider.jar