From 99904f4bd990a9c259633b1de096e198a0487fdf Mon Sep 17 00:00:00 2001
From: nathan
*
* {@code * Growl.create() @@ -50,26 +51,14 @@ class Growl { public static final int FOREVER = 0; + /** + * Location of the dialog image resources. By default they must be in the 'resources' directory relative to the application + */ + public static String IMAGE_PATH = "resources"; + private static MapimageCache = new HashMap (4); private static Map imageIconCache = new HashMap (4); - String title; - String text; - Pos position = Pos.BOTTOM_RIGHT; - - int hideAfterDurationInMillis = 5000; - boolean hideCloseButton; - boolean isDark = false; - - int screenNumber = Short.MIN_VALUE; - - private Image graphic; - private ActionHandler onAction; - private GrowlPopup growlPopup; - private String name; - private int shakeDurationInMillis = 0; - private int shakeAmplitude = 0; - /** * Builder pattern to create the growl notification. */ @@ -78,6 +67,69 @@ class Growl { return new Growl(); } + /** + * Permits one to override the default images for the dialogs. This is NOT thread safe, and must be performed BEFORE using the GROWL + * system. + * + * The image names are as follows: + *
+ * 'dialog-confirm.png' 'dialog-error.png' 'dialog-information.png' 'dialog-warning.png' + * + * @param imageName the name of the image, either your own if you want want it cached, or one of the above. + * @param image the BufferedImage that you want to cache. + */ + public static + void setImagePath(String imageName, BufferedImage image) { + if (imageCache.containsKey(imageName)) { + throw new RuntimeException("Unable to set an image that already has been set. This action must be done as soon as possible."); + } + + imageCache.put(imageName, image); + } + + private static + BufferedImage getImage(String imageName) { + BufferedImage bufferedImage = imageCache.get(imageName); + InputStream resourceAsStream = null; + try { + if (bufferedImage == null) { + String name = IMAGE_PATH + File.separatorChar + imageName; + + resourceAsStream = LocationResolver.getResourceAsStream(name); + + bufferedImage = ImageIO.read(resourceAsStream); + imageCache.put(imageName, bufferedImage); + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (resourceAsStream != null) { + try { + resourceAsStream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + return bufferedImage; + } + + + String title; + String text; + Pos position = Pos.BOTTOM_RIGHT; + int hideAfterDurationInMillis = 5000; + boolean hideCloseButton; + boolean isDark = false; + int screenNumber = Short.MIN_VALUE; + private Image graphic; + private ActionHandler
onAction; + private GrowlPopup growlPopup; + private String name; + private int shakeDurationInMillis = 0; + private int shakeAmplitude = 0; + private Growl() { } @@ -163,7 +215,7 @@ class Growl { */ public void showWarning() { - name = "/dorkbox/util/growl/dialog-warning.png"; + name = "dialog-warning.png"; graphic(getImage(name)); show(); } @@ -173,7 +225,7 @@ class Growl { */ public void showInformation() { - name = "/dorkbox/util/growl/dialog-information.png"; + name = "dialog-information.png"; graphic(getImage(name)); show(); } @@ -183,7 +235,7 @@ class Growl { */ public void showError() { - name = "/dorkbox/util/growl/dialog-error.png"; + name = "dialog-error.png"; graphic(getImage(name)); show(); } @@ -193,7 +245,7 @@ class Growl { */ public void showConfirm() { - name = "/dorkbox/util/growl/dialog-confirm.png"; + name = "dialog-confirm.png"; graphic(getImage(name)); show(); } @@ -282,7 +334,6 @@ class Growl { }); } - /** * Specifies which screen to display on. If <0, it will show on screen 0. If > max-screens, it will show on the last screen. */ @@ -300,20 +351,5 @@ class Growl { growlPopup = null; graphic = null; } - - private - BufferedImage getImage(String imageName) { - BufferedImage bufferedImage = imageCache.get(imageName); - try { - if (bufferedImage == null) { - bufferedImage = ImageIO.read(Growl.class.getResourceAsStream(imageName)); - imageCache.put(imageName, bufferedImage); - } - } catch (IOException e) { - e.printStackTrace(); - } - - return bufferedImage; - } } diff --git a/src/dorkbox/util/growl/GrowlPopup.java b/src/dorkbox/util/growl/GrowlPopup.java index 7dcc73b..cc2c550 100644 --- a/src/dorkbox/util/growl/GrowlPopup.java +++ b/src/dorkbox/util/growl/GrowlPopup.java @@ -364,7 +364,6 @@ class GrowlPopup extends JFrame { // popups at TOP grow down, popups at BOTTOM grow up int targetY; - if (isShowFromTop(position)) { targetY = anchorY + (popupIndex * (HEIGHT + 10)); } @@ -377,7 +376,7 @@ class GrowlPopup extends JFrame { if (notification.hideAfterDurationInMillis > 0 && hideTween == null) { // begin a timeline to get rid of the popup (default is 5 seconds) - hideTween = Tween.set(this, 0, accessor) + hideTween = Tween.set(this, GrowlPopupAccessor.OPACITY, accessor) .delay(FADE_DURATION + (notification.hideAfterDurationInMillis / 1000.0F)) .target(0) .addCallback(new TweenCallback() { @@ -388,10 +387,10 @@ class GrowlPopup extends JFrame { } }); tweenManager.add(hideTween); - } - if (!timer.isRunning()) { - timer.start(); + if (!timer.isRunning()) { + timer.start(); + } } } } @@ -407,8 +406,28 @@ class GrowlPopup extends JFrame { final int popupIndex = this.popupIndex; final ArrayList growlPopups = popups.get(idAndPosition); int length = growlPopups.size(); + final ArrayList copies = new ArrayList (length); + // if we are the LAST tween, don't adjust anything (since nothing will move anyways) + if (popupIndex == length - 1) { + growlPopups.remove(popupIndex); + + if (tween != null) { + tween.kill(); + } + if (hideTween != null) { + hideTween.kill(); + } + + // if there's nothing left, stop the timer. + if (copies.isEmpty()) { + timer.stop(); + } + return; + } + + int adjustedI = 0; for (int i = 0; i < length; i++) { final GrowlPopup popup = growlPopups.get(i); @@ -418,6 +437,7 @@ class GrowlPopup extends JFrame { } if (i != popupIndex) { + // move the others into the correct position int newPopupIndex = adjustedI++; popup.popupIndex = newPopupIndex; @@ -433,14 +453,15 @@ class GrowlPopup extends JFrame { copies.add(popup); // now animate that popup to it's new location - Tween tween = Tween.to(popup, 1, accessor, MOVE_DURATION) + Tween tween = Tween.to(popup, GrowlPopupAccessor.Y_POS, accessor, MOVE_DURATION) .target((float) changedY) .ease(TweenEquations.Linear); tweenManager.add(tween); popup.tween = tween; - } else { - if (this.hideTween != null) { + } + else { + if (hideTween != null) { hideTween.kill(); } } @@ -453,6 +474,10 @@ class GrowlPopup extends JFrame { if (copies.isEmpty()) { timer.stop(); } + else if (!timer.isRunning()) { + tweenManager.resetUpdateTime(); + timer.start(); + } } } @@ -483,7 +508,7 @@ class GrowlPopup extends JFrame { void shake(final int durationInMillis, final int amplitude) { System.err.println("shake"); - Tween tween = Tween.to(this, 2, accessor, 0.05F) + Tween tween = Tween.to(this, GrowlPopupAccessor.X_Y_POS, accessor, 0.05F) .targetRelative(amplitude, amplitude) .repeatAutoReverse(durationInMillis / 50, 0) .ease(TweenEquations.Linear); diff --git a/src/dorkbox/util/growl/GrowlPopupAccessor.java b/src/dorkbox/util/growl/GrowlPopupAccessor.java index 670d31a..e5c33eb 100644 --- a/src/dorkbox/util/growl/GrowlPopupAccessor.java +++ b/src/dorkbox/util/growl/GrowlPopupAccessor.java @@ -19,6 +19,11 @@ import dorkbox.util.tweenengine.TweenAccessor; class GrowlPopupAccessor implements TweenAccessor { + static final int OPACITY = 0; + static final int Y_POS = 1; + static final int X_Y_POS = 2; + + GrowlPopupAccessor() { } @@ -26,13 +31,13 @@ class GrowlPopupAccessor implements TweenAccessor { public int getValues(final GrowlPopup target, final int tweenType, final float[] returnValues) { switch (tweenType) { - case 0: + case OPACITY: returnValues[0] = target.getOpacity_Compat(); return 1; - case 1: + case Y_POS: returnValues[0] = (float) target.getY(); return 1; - case 2: + case X_Y_POS: returnValues[0] = (float) target.getX(); returnValues[1] = (float) target.getY(); return 2; @@ -44,13 +49,14 @@ class GrowlPopupAccessor implements TweenAccessor { public void setValues(final GrowlPopup target, final int tweenType, final float[] newValues) { switch (tweenType) { - case 0: + case OPACITY: target.setOpacity_Compat(newValues[0]); return; - case 1: + case Y_POS: //noinspection NumericCastThatLosesPrecision target.setY((int) newValues[0]); - case 2: + return; + case X_Y_POS: //noinspection NumericCastThatLosesPrecision target.setLocation((int) newValues[0], (int) newValues[1]); } diff --git a/src/dorkbox/util/growl/WindowUtil_Java7plus.java b/src/dorkbox/util/growl/WindowUtil_Java7plus.java index a99fb05..cc6ad04 100644 --- a/src/dorkbox/util/growl/WindowUtil_Java7plus.java +++ b/src/dorkbox/util/growl/WindowUtil_Java7plus.java @@ -4,9 +4,6 @@ import java.awt.Window; class WindowUtil_Java7plus implements WindowUtil { - String test = "asdasd"; - static String basdasdasd = "asdasdasdasdasd"; - @Override public float getOpacity(final Window window) { diff --git a/src/dorkbox/util/growl/dialog-confirm.png b/src/dorkbox/util/growl/dialog-confirm.png deleted file mode 100644 index adb569bece45425ad0742a5b894ae9766596efe9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3901 zcmV-D55n+?P) n>gj9>;771>R&Au4n_HodTP_j~=;dQ~;QTc^5C C&aMOG`^f0T@X1 zA;RSECq9!d;(^a1(6oUe@@J^F^Ks;WVNZB`e~IJeDYGO2Ut&Ye1O z;>2rDKKbOnGiT0x1fY#b5(dYZ|0e_-EBT4yKp;>_tA2a-?AhOnMx*@)}(_4#} ~p5$k^~gd|)56cU3sY}jyTeSQ7z zMT-`#E-o(amrkdVk5nq A5d$-n@D1>#x85G(&JQfWAafp?ppPZmf&d z%O*{lG@jPlx^m^pb$$Ex9gwH+r-pZIE|=3d|D4^scfY)8)28JBs)$HWxuNzV-u*=1 zB} KpL*)4&5ZR*S;Pac1tB7FUEgM4|JgWx`PL=;_?1RH{rhITbo?sb zI-f+E-84;;9FSbepG#UXfO6AKH!V7S`t;_Snwk+ViBIVPA5q3FaV~e6^-S7={KW)f zRZ-@>79Ibzrx|lM{s~LBG+^_QIF2`2NGTCCbo%kzGfDj8?nX?1>@>dh^FQMG!_Cl5 zJCVgZE(tGcYiqx_ef##GIa_X6q4Y$+o3KT5=gyt9X3d%(@q0kR!b?ED%Y60i2JZdO zMtpxq6a3)<{KHK(`0gzu@trT%VBQx7 1XFXF|w z8u4#;UW*~okdTlyy!v3qj2R1=*zYf2zWnC^E)ltpeGWJ~PUZgn`+veXT##=OQQo41 z9^Tc0_Kb?_seB|7hN`F}rXwEfL}xsPV$DKvSVgqZk8r?;mi82`CUP93prEi2;ZOij z06m*SebW`3IM*mq6Zws_5pMZ=U)R z1wg=?Tw+m`R=nq>X88Oej2Y4wfuQhJU>YW}iFS-DS1|Ls0VpqxpgZ~KQVh@UKZp9b zg5shg@eE1mh{Zec%JF*qc=0G9A)XL@gn*0V$B*w}sj>n `FRSb~; ztu0EskYxRr16Pr@0vI~5964VAshom@ZlN=6B9%;I(ezqZ`R*{FyciEHx*lWuX=uF~ zM=YfyZCFqPAxs`sjR$^Rhx#k&uH<&t7F{Mxm@w RJ4ZV@O=8T1vO`;=_MV#Z4oJS*x z;njVx?Ag;WEr`MFwYzkoXscJRz7Ied;mh}c9X@|gA#+s*b-}K2*njKs4h*S`+LmWH zBVj9V*=;gs!SDrfxULl Na k^?NjHUt^uObxoF z;a7(maOaG{vX&bOgyg~u0KXvGG*9?M=Fgx1Ri`9&I}5izw&akeb#=nj#Zurx(%Qpf?p{ECZI~NxS8E&F{zlQ!QBb B(#eGo*mt(m-Zs D3$=Q}WUM5%2^?_p{1;K9|Rv)2O}36$oSz#<)4* yi3}8=Go3@e z2#F8{Vpn%bz>HJSjT8sS9#-%5Hw{!5SQy&B1YX&&;}n{+K`2^4T-(DW0t*#o!S2d^ zT&0N4UJv9*pu_24!zB>30K@nc=C@E2^&?-7oR2~E2W5d?&SPRgG~$Mh7nd(zZV{cm z9?(gkP1reb-Bn(waV|UEdhLOV(h&0H?4>No0D#i7@}|kgz=*0M@70WphK7bl(b-EN z8;iwSoO>Jh?nVYq9abbsX;0dd2yZF5U#W}XOKbMvhVSmc7l|9czZ>ncZTe*X9ynME zxFD*E{1{nP=q9h|BM>=u>{vs-2a=~wojNQXypVyjYQun@B8hCbd#2(j?o&ycA6Tv+ z6D-1oY%wkvCAgp$;loTJ{NV^R4ba%nCq#+v$%qFGOdVbB-FaLBEiEk#JlI?WU}zo! zY2H2@;PuJF>=b1E<5q%&Oya+((C}_YLK4ucIKc%}=T=t~l7AL|%_*oX4PxPhD(Qi( z@3f#X0lTWr8B$^p?30t$1k5fHqO6$%a#<{%I>>8%7iZ6&eG@?3C16n)GCFVDT0i{o z!#@lgHf)j*AlxV5JyWAt`eG|gf0$t`Bpj=23N30OpwjX_%k}_rCax`0@vloJxcRzl zMh%v3K8h2~227PCbReBI2_G^lkjYrE!(RT;(| NPi!SBPvQF8X`dzeocHQd8 s z-feAdZLK8W4ib@x*32wNiJCwz*=dvT(eiRO50gYtVw*9fiUn!jk<}&0myrXcaMQ(0 zcHdw?MTp9WZ2~G3hK`a=V%f}VP}@IZ6UevzfddD&I2XV<0xkhz10YL=O*?n)-0U!x zgp}4MP!_WA_}8o8OLZWZO4wT~q-M!8wL
Dj8KyOFK<*R6qr4dgUNTlU(t{|rdkP1cdgFW?_^1bbt{Jq~`?XL4k21@LcRx)Ft zGnL~w9c^+m(bk5qUl+yJdnVEdruX>h65s}Nf(QDST 1cE_YUxO;SK%$b6MmBAi#|nRkLUOtZJ x;1aV{dRwzfW~_ZJzdw`cK{>%`SI-H z!HA^|?0YYc*Unr e(OH%oHUdhP z$Hqsg{6PR6gxTA7WZtXBLLQ*6;meJG7Eg%c;sNia7sU;$ykgK>6uNCbM0sc1b_wui zq@C~09w2r*7rMGd=`DeL5)q<`IkA%Wt9NrjUzhSu>v}^7c;S(5Nr>WJ ;&* zTD6kb>PG>z=PTb+2<7KO!0DIdOTAyMSh1p+lP{~Tt{zAdvbamYNkTUfyA$slO2SJ( z2 ~oSh=pf{vfG8s>AAIn^*?eBi;j^ODQQk|! zYh~}eE&(qIip4jSr`N7syY1x3lXU=Ei8zrY(nQ8ViX_e6ykgQE`17C=S>p2g_3QVJ z7%^fU+g;q=>N#;vj;Y~rxYuA=+|E}>N9WC(x8assZh4x@pLG;B318mY8lm<&2b_D; zAQ8#)M8M;n0-~5G<@@63?YG}PZu<1;wY)JXB?_4Q;j*%_5Z^E4SYM@ij7_psiL>Hu z;-4X$IDGi<1&MJ72_oen>#=--NIH4Y!!FeG8+yVe6L!e>J*2`8DZeLol)OLo5TuBt z)24~6S9upbzpd|?KrfP90LSI3!1G!05HMXhgdA8sDcK`||IhN@>*)sHD`8J200000 LNkvXXu0mjfNu-CV diff --git a/src/dorkbox/util/growl/dialog-error.png b/src/dorkbox/util/growl/dialog-error.png deleted file mode 100644 index 769d7df7113350020cf67b19aad6629f68732a49..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2561 zcmV+c3jXzpP) B+}8WLm^z_a?vG zJNLVD?(f|5xM$`|iO1vgzuW@JEK1?VU62uy{?fJxV;FrriPKdJBqBbAyF5lVBa1PE zkxG}gjWGHcCmH>WZss_Ua5X=4LoJifSXy0Oy BL|z@B; vkba9w-0Ds;a8$y1Ke$>FMbics?>RLeXecNkD-_W7~Vp zCnW<7O3a)&lR}{og~Q=9wY9Y$H8nLg645ujE}BSzd_MVQEiEm71$hXIL?TxBFQ$a@ z%FWHCoSYm{qO7d!Z)}N=_}LFu0UNNDyLRnb4Y$EO+(iX?m>l!&xkU4BB|OLKqOdlg z&-3!~poF+nd3pIdBHE^bZ51fyp!rKfL&GXd%94qkJxhb#-4r=@j#7L+fn-?p7Jfew z=C!FT#E*grqK`Q}K*1mdr%y*OmLD1#(*3EpxLDk&rlw|NV`Jlbme;1)M)Q1jMMXuC zo*{L!OFsi>%kz>yWm24`d~y~u)$tdf$FT+KEh4nT>v zEnDdDXP;3pJsl= w0w^kT;5`JE7P8d%pgfGOxOd{DFY-5hcJ8Tpi9MK4XDY%{*3#{zHc#90YVzm|Kv4 z!wr;QSt%|M#T=U(^HJ`jycv2x=FM2YpK L!|-9&*vKrGU=ZJQAA@j8hUhLasMh?N-JM2KfFFc0!S z?$`k m0NPfoRU{%;PnVP^bj`tjyq`9t+%S8G@BK{xa-R=K|sjIc%8<8 zx||}byqu;nG)+%sSBbLxAL08Bd09)+luL5eC A0R>Dxf5{SgZWS%O`DR&n z MM;E^qS(;63HoGiK!s927(S_3l%*3 zmRn@~;m^b-yB_akLP z#>8Dn8~i`a!7Lhck=6e0yAUi&*!6xVb 68Sj!lCU$>D=1PSEZrpQJr6ya00I8X6CZ zxp&@4g{+8`sl^&f^o|W1sQvZVDZ=S8MY9%8--){vj{qKb5W|!<|GV41mtPj)SFBzw zy*qEap~@U?XrL~*qEj A}#u0=-G0=qD7!S^}s)dMdG(-3iaGeD+zp8G1KF{`Y+H zolQ+}7Z3-)6q`#HQ;;i&F&=jiYmK5OWEHUZ=EWC<^rGjULoj=i$NYD1yg?le4P)|* zT&+gqssND wd@HsK&fI)q@1?S}4F z#sU3@r=C)!tqa+^g62Q+2o*o{P$KfSO0_WsB(H$Gq#kvCaOe*iw*vDYdyGmSf873S zVPoMumnwPS0h+gJl_d}8SWjQc+W;QF1<*&G5*V&ye}$p_?$Jl7q_);G Mn&w$a~^z9$)1P3uf9rq>*{D9UsU@!^QZ!D zaz%WT7gkq`+h{XutP&Heg^)3VOjwm6lm>iid0bXoq4xB@ee+HF*IRGFN}}-o`g)oF zJ^Q{AvX}=ea_qG8_e^saauahQ04EM55OlxdUt&32oLOO3fmXhxS{oXKJQ_|Gb 2w+|IY_!FS$4Afl?2;!pc1;~&pI zPkUJr6BF)q`}4Sv`zIxWD}4O8Sm5m2ZzFSv8`(`dH*LZVtHC(-FNEvY)t+_h m&*j-e3*T#*Qf`w3OjL8WGVF^Hj-(AJ(KHqU{ zc(ut{S+*7e5-Jd3jNl(&{#!f4x={MuxmxCuyB%$8l-^p1fFxTB-xFR<4`cd*1=fY+ z4gp7S1!o(?!;HQoM~)n41?>Mr 2}4_Pt&An(`*(J1;7zp!P#wrldY|- z|0yjkErt?jIcumT3i+}@`<^q5TH;axC%^ESX9Q$UKj73~;0Uh5Srv$LV-5S8o0~h9 zFJHbGZ${eM+Au$+1Ybh4?!KGC?d=pD81PDQUcIidNVpC@pHo&wp{Y~P%Z903zMz34 zcm3de!5198y}i`k-L1lHpTyinuXm?(!1D!%f6baTgvR~I+O=y3ckbLdx^m^pD>E}Q zLr&1xlxD{lp1b( RXCXY##?ZsKmd4a5sId;za@@Ma_pH!zX+E26}6 z6JD>qDxoj=zzrM?-=tr&>i_eAy%{Yodd`*@Xo+64{@=goRt5ZwX^cGQjYu{lhY@mI zFU9m^#sHb#B5ry>OlijGhZ#MLQ%=7BH{&!T<{)Z0LjjQXJEVi?EzJBRMw-*>dWB!- zJm!5Mr<+??QU*`}ZZgD(=)8qi4j3o0fX@Sd?GwSQ2^bk@qXsdBRm^_YvBG|iy9oam X*VUb;*LIwL00000NkvXXu0mjfoi5}! diff --git a/src/dorkbox/util/growl/dialog-information.png b/src/dorkbox/util/growl/dialog-information.png deleted file mode 100644 index a220108dcf27810ecab177dd7969c7d3d05eae99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3594 zcmV+l4)yVgP) b&f-MO)BqgRv+l01xKJNRR @JIpR6&bn?Xn>T+6j`k8OXxL5;9{W(nk$NmDn()b zP3dcvm}rvH*QZ2-{9F1rF9yK42=I`o0l-qxn%_ySHuI_P~Jy2Y%4m+4;!XvuA&t zOeP xE$$s`mMOYy(3>LuU^jJlM5m%a#MXckli?fOb)z@T4xa0q*>+5Y1b%WJ%NJ&6}H> znwmby-_z+dDDk!fZCRF6yRTWo;jkkBc57?v;f)(N?v@C(0%#NU+fpu-0fhGfs4FZi zy#A@Do?5?R#ft01n|?y4QmHIRYC0n*&4;3*B8q>fUwGk#S2t|fux)g7bT5Fng)MWj zV}S5M01M{MoxAq+*I)m}%9Sgd 20~Dm?Em~Iyr{z``*TncD#X2&-??Mesc(q zJ^v>Dc(51Urzd%zb1wj<5{@4~j`8tvKig&>?2CP}?~5`(!(Y34_3HKe_wWDe<(FSR zlb)m8;D@?S 4-CD&fw(9lb9)meX&pWeLf?M^Q6sH0>5_q_U(5R6cj{s4m;p|N=$ z({pI~-cG#HJ&5Y63aq%X3AZ(W6yN^bP58f!&G_Zln{og8Ww`aGC0KLwQZz2U29u^A z5B~O_xa09w9F>Uah#(e=p|`h}V {?OH!GkX@wOA4@PRslZJP>e{fA4Q_3h6om45k+CxhiE}A z8tP}^L)Tq{KwcF0Z+#Wt5o2^j!G352J F0}W+Cf+%G&8I^LgD|3%)|$Uqh{O>IE-JU@@K4Rbyoj}t<{PbAX#$h}XaqxUQ- ztE*8}JyXIRg3s{4D>8Izra%+kEn7v-hTO(`MXH8h462${j}a>e8y@|eV+5ZW7#IK< z$U-K~cHRioaGvK>NzYS+XZoz(v;zY}6Nr|TqcB 0j;p5{ $#=6c-nJ$hKRGaPci| zo|{6sqFTwdhD0LaOqp-?4rAZp9vI 6u4$pwi}+g)^{Hq>ZQC*J4114sasj z7JnO_NMSUdh7G_pf_U!W34C+yRb){Hl$Ms3kWsH*$Fu>?i>q?ox^)WxaP&Kit-l@V zm9z=M;}0nh$5TlZ=lR{!rn;BWH$_}B>o%3#*Rh1DqL (l48qWza5`rpqZm*r$UU|c9RaY{aD9D!iJtb
!YB(;2 z1W=M6fHpu6W_wx#7y)s%g3ss~>-2aML*prxP9EJBSQ`O!y)z_+#ZeUrF$#){jAYf! z8J}x9&5cH*`TC^=miFEuScVU_#|xq`TQn1fB-~Ue;6*e~j424<$rpR@tG&nJ71#|+ zYw)SY$}9uub*9OgQJpTfYE!rEVJa#~1 >kQ)A75VVkrnDmvoL&t> zz`0B?2q^M!R>^`Vpsgdo)X^!WBfxrEcuka%zB8D2S;QH{Y>SNA0PEZc#Eu<1b~Yy` zN8P9*P!vFINf Qmeto);diY)0+a;I zButN5(5bah&~GpbDk{RsWr8!q*m?}GA194KXa$=!+pxI3@3qtT^s;&<|7if($Vk?# z#hlKoUO64>T)upHiOxIJ&j_P&b}9CEjl(eGFnoT2;F5x40m#wb&!| V`<&Y4u UJKq?%TI-ZcR;%Uq(Gx z?p 0_@# fR(kG9OmPxf?Ud#j8IQ_b0c*N+3o42;E6kgfrP>ju5*gGkRz9u5y! zKypGo7w}~8rRF*K?q{x5n mx)erEmBh^YX$B_1|MHojR$U9h`P!`r%g_mvKpYX60&`K za>tGx^!^dy%uH{<^vCOKdC oljEVRCg+?236;FwI(8{w)zNP#6 z`kaF=xB5p?=o*-mI)Qgak}448MPbyG<_T~CYD@DSVD~ba r7`*6@e1y9o>Ah&3Xq6l?JtAIvS>6+8Y+dA3&z_i=u;o0{ zmQ=Il8?i0M*)sU;R4PR-B|gJv*#_IvZ3Zrshbi>FKXmKk?kZ6&Pt17e#B&=Seem=^ zZ@|?ykUJ@EM!25ml31@QdqpSp_u=>@{m`usd;Ko?T-RP#&4}cQBBC-;NGmJ~YJh|& z?$T+|uxLV*7G*@H>zYbCwU)4&QySorqG5upUCJS>>pI|qrwn)PGM3`Ko@_{%T2}V8 zf=!8%tliSTCA2bArVwp$0r^ }P) sjC%HOKO!SP5*G)_z{gw)%ZpH*!{yqjd7dw zYi*>!ZdamBo7kjw{b-unEsY4))zWTK%ZkZTSQZe20yE6an|bp-dd@ia@n%LC7+@zo z@#Nll@80YAo!`0V-t*veU5Ec?5n&F5<2Y(8s41vAY5-N43up1OY`BP;gWaX5Yf--& z)+%~N?`TYN0K_-mip^Jxi;H)hJ9qBX-Me>xGCDf?4(d7T(=&QUV`yx00mK@gicLjz zb@dx}?%X+k=+L2WFJHdATogrzAPA0%ii&c2M(=10jSbI9K7epYly5`1diCnQ)YMeR zlP6DLaBvVtMn*!~-`@{?eSKiDSR6El#?qYd+@v$G(CKups;{sA9`@5PWB@lS0W*~6 zc~DgqhK7b97!0P-Seip~lL>%~OQ+4*)YSBb)oQhSy =_ z-q*cg^ZyNOfmTQlwn2t+8wBu0gp=FthPU57TSIHmT3;vt=KX#9_H9^*f^lu~K7iHJ z44m=|bWI|~{xGB=7@i+zhyY|~FIY%x%!CDg2Hr0@cI@Z|@;-^-ed#{{!6DF9KdNLX zr#=OX{LlbO;&Qp*tv74GNoys_0^NlY@qWpkJ$q^~o9y!Y{h( #&-aqLr0nIyAT W=+UE9ilP`H zK_IlzR @#r@js(j0IW?0elDmpP`P;b_fXs!sLA?djA`X7cVXZ z6eISzAgCj^D0IT=iwq;h7ivZC-$CFNV;(V>pPyeyYtq`p@LVupL6yzk$2P+I!J$6` zC@#=Lp69{i=ixVh;ecdYH9%Ub2B4FAL2x6`jOx%l6xz@Uv%pW`Jpm9qJ3Fn+`$a`X zh31XR=>Y`rr*Us e=2433SBCBy UJXbkj+7Hw!UXZ(g1iUUWCnU^*7zZ3F zcj3Z?d3d8N# iub<| z82$*9u})B>UhsLIl2=0;)IHJ%iu)6gL+>Ajj7LEL?*XUzjJ-gIBC)V{@7@iJg+v(; z7y}nCUYz&%@#B)+yLW$`{sZPMYNf89gBEmwA-aMdehehTPtu^X(*`8&Vjn*DLbT|L z8$r|~3&)H#=|+3x$dPpo4Gn)~EKHXHo_Qb3L9w;9)wy}|=E~gM+ &gb)mScq3I5CBWG;$#cOK7K){#Or<@<#J}crg+d}?@}fq z{$Z8`0W<)oN#=|cmjwpEN@@ZiHa9nC_V)IcZr{FrHKjr3eNv_GUG)A_X8f$OAotcq zl%D9gxGWe9Fd!J~DQ#_S&dSQlH90vsxyXju`v{<6O2((BsxkfeEYuSV48)XJ5K&W1 zd0)79@1Fg^g9oo-2KXAL(TKbc{SBZ8hhZvGSuzSO5A3WzEf%bW$5|pE7ADO|RFUN~ z<1q)TwY9Z{Sy@@TPn H9IKOF(sew>v0(`UiobDnMHiCJI(a6sVZ&6_!RVOx) H)!OwTd*r;cx(DAr?jf zTNS89Eg<+i@V7>bL@T>4zp#xzK6V_5U@HP4eTljLHVUKk^z; I?j${XU+`Kf~vp!l_fI;PmO!a(8$4yscZe zR%B;qJE)Rke=0&D0OmISvzd>NW`r3})tVd6tR@6>A8q$D01A!i>FG(`v}x08cDwzh z%*;&M&~yqW9Ry=VQIz1xlP5pGTID7HbRhtpGkKZfs ocX&E~)Q6&? z=t&T~5sYBI|2KY6`{T-$D^CN!>!_(_n;8RU+6Z 8N_M^rg4mpHk^cu^13<^farG